در ارتباط با سرور مشکلی به وجود آمده است. لطفا چند دقیقه نقاشی بکشید!

حتما این بازی رو کردید:

بعضی وقتا بد نیست وقتایی که اینترنت کاربر مشکل داره یا سرور شلوغه و … یه آب نبات بهش بدیم تا یکم سرگرم بشه.

امروز صبح وقتی میخواستم وارد ویرگول بشم با همچین صفحه ای رو به رو شدم. چیزی که نظرم رو جلب کرد این بود که تقریبا صفحه خالی خالیه!

چرا اون وسط نباید یه بوم نقاشی باشه که کاربر باهاش حال کنه و چرا ما نباید اون رو بسازیم؟؟ من که میگم بسازیم چون خیلی حوصلم سر رفته.

این چیزیه که خواهیم ساخت:

منو بابت دست خط خرچنگ قوباغه ام ببخشید 🙂

اگر حوصله خوندن ندارید میتونید کد ها رو تو گیتهاب ببینید. و اگر خواستید چیزی بهش اضافه کنید به شدت استقبال میکنم.

کار با canvas

اگر قبلا با canvas کار کردید این بخش چیز خاصی برای شما نداره. فقط میخوام در کوتاه ترین زمان ممکن چیز هایی که نیاز داریم رو بهتون یاد بدم.

معادل بوم نقاشی توی HTML میشه canvas. اینطوری یه بوم نقاشی میسازیم:

<canvas id=&quotcanvas&quot></canvas>

و میتونیم با جاوااسکریپت هر چی خواستیم توش بکشیم. اول باید اون رو توی صفحه پیدا کنیم:

const canvas = document.querySelector(&quot#canvas&quot)

بهش میگیم میخوایم یه نقاشی دو بعدی بکشیم:

const context = canvas.getContext('2d');

از این به بعد به context میگیم که چی میخوایم بکشیم و اون هم میگه چشم.

قبل از اینکه یه مستطیل بکشیم باید یه چیزی رو در مورد محور های canvas بدونید.

تنها تفاوت محور canvas با محور خودمون اینه که جهت مثبت محور y به سمت پایینه

الان یه مستطیل سبز میکشیم.

context.fillStyle = 'green';
context.fillRect(10, 10, 150, 100);

دو پارامتر اول به ترتیب x و y نقطه شروع و دو پارامتر دوم به ترتیب طول و عرض رو مشخص میکنه. صفحه مانیتور رو یه محور (از نوع canvas) تصور کنید. زود باشید! یکم قوه تخیل تون رو به کار بندازید!

با یک تغییر کوچیک مستطیل رو تو خالی میکنیم:

context.strokeRect(10, 10, 150, 100);

میتونیم خط هم بکشیم. اول باید بگیم میخوایم یه خط بکشیم:

    context.beginPath();

که از اینجا شروع میشه:

    context.moveTo(75, 50);

مثل این میمونه که بگیم قلم رو بذار توی مختصات 75 و 50 صفحه.

و یک خط بکش:

    context.lineTo(100, 75);

قلم الان در موقعیت 100 و 75 وایساده. از همونجا برو به موقعیت 100 و 25 :

    context.lineTo(100, 25);

و سر و تهش رو هم بیار:

context.fill()

تا همینجا بسه. اگر اطلاعات و مثال های بیشتری خواستید اینجا میتونید پیدا کنید.

بوم نقاشی

اول بخش html رو انجام میدیم که بعدا بریم سراغ اصل کار.

مشخصه که یک فایل app.js و style.css هم ساختیم. اگر ابهامی در مورد این وجود داشت امیدوارد چند دقیقه دیگه رفع بشه.

باور کنید توی فایل css چیز خاصی نیست که توضیح بدم. میتونید از گیتهاب ببینیدش ولی به دلایل منطقی اینجا نمیگذارمش.

بریم سراغ بخش اصلی که جاوااسکریپت باشه. این شروع میکنیم. یه event listener که وقتی صفحه لود شد یه context از canvas میسازه و همه چیز هایی که لازم داریم رو از html میکشه بیرون.

window.addEventListener('load', () => {
    const canvas = document.querySelector(&quot#canvas&quot)
    const context = canvas.getContext('2d')
    const clearBtn = document.querySelector('.clear')
    const pens = document.querySelectorAll('.pen')
    const colors = document.querySelectorAll('.color')
    const container = document.querySelector('.container')
})

طول و عرض canvas رو نباید با css تغییر بدیم چون تنها کاری که میکنه اینه که زوم میکنه و اگر زیادی زوم کنه اثر هنری مون پیکسل پیکسلی میشه و ضد حال بزرگیه. بجاش باید با جاوااسکریپت این کار رو کنیم.

یک بخش حیاتی داریم. قسمت بالای صفحه رنگ ها و قلم هایی که داریم رو نمایش میشه که بخشی از عرض صفحه رو به خودش اختصاص میده(اسمش رو tools گذاشتم) . باید عرض این قسمت رو از عرض کل صفحه کم کنیم تا عرض قسمت بوم نقاشی به دست بیاد در غیر این این صورت بوم نقاشی بزرگتر از صفحه میشه که در اینجا چیز خوش آیندی نیست. میخوایم همه چی تو دید باشه نه اینکه بریم پایین(اسکرول کنیم) تا اون رو ببینیم.

 const toolsHeight = document.querySelector('.tools').clientHeight
canvas.height = window.innerHeight - toolsHeight
canvas.width = window.innerWidth

از clientHeight عرض قسمت tools رو به دست میاریم و window.innerHeight و window.innerWidth هم به ترتیب عرض و طول کل صفحه رو به ما میده.

سه متغیر مهم داریم که اولی نشون میشه که الان در حال نقاشی هستیم یا نه، دومی سایز قلم و سومی رنگ قلم رو مشخص میکنه.

let painting = false
let penSize = 5
let penColor = 'black'

نقشه اینه:

وقتی کاربر کلید ماوس رو فشار داد یه event listener میسازیم که موقعیت ماوس رو لحظه به لحظه گزارش میده. یک خط بین موقعیت قبلی ماوس و موقعیت فعلی رسم میکنیم و وقتی کاربر ماوس رو ول کرد این event listener رو بر میداریم.

canvas.addEventListener(&quotmousedown&quot, startDraw)
canvas.addEventListener(&quotmouseup&quot, endDraw)
canvas.addEventListener(&quotmousemove&quot, draw)

و متد های عزیز:

const startDraw = (e) => {
    painting = true
    draw(e)
}

const endDraw = () => {
    painting = false
    context.beginPath()
}

خط پررنگ شده رو یک بار برداری و ببینید چی میشه. اگر این نباشه وقتی بعد از ول کردن ماوس دوباره اون رو فشار بدیم فکر میکنه این ادامه خط قبلیه و یک خط مستقیم بین جایی که ماوس ول شده و موقعیت فعلی رسم میکنه. با این خط بهش میگیم هر وقت ماوس رو ول کردیم داریم یک خط جدید میکشیم.

const draw = (e) => {
    if(!painting) return;
    context.lineWidth = penSize;
    context.strokeStyle = penColor
    context.lineCap = 'round'

    context.lineTo(e.clientX, e.clientY - toolsHeight)
    context.stroke()
    context.beginPath()
    context.moveTo(e.clientX, e.clientY - toolsHeight)
}

خط ۲: اگر در حال نقاشی نبودیم فوری برو بیرون

خط 3 تا 5: سایز قلم و رنگ اون رو مشخص میکنیم. در ضمت میگیم میخوایم گوشه های قلم مون گرد باشه (مستطیلی نباشه).

بقیه: یک خط از جایی که قبلا بودیم به موقعیت فعلی رسم کن و یک خط جدید رو از همونجا شروع کن. این چهار خط رو چند بار پشت سر هم تصور کنید تا بفهمید چی میشه.

خیلی چیز ها کم داره. اولینش دکمه ایه که همه چیز رو پاک میکنه (به svg اخر html نگاه کنید).

clearBtn.addEventListener('click', clear)

const clear = () => {
    context.clearRect(0, 0, canvas.width, canvas.height);
}

برای تغییر اندازه قلم هم این کار ها رو میکنیم

pens.forEach(pen => {
    pen.addEventListener('click', handlePenChange)
})

const handlePenChange = (e) => {
    switch(e.target.classList[1]){
        case 'small':
            penSize = 5
            break
        case 'medium':
            penSize = 10
            break
        case 'large':
            penSize = 15
            break
    }


    document.querySelector('.activePen').classList.remove('activePen')
    e.target.classList.add('activePen')
}

کلاس activePen و activeColor (که بعدا میبینیمش) با یک قاب سبز نشون میده کدوم قلم و رنگ در حال حاضر انتخاب شده. دو خط آخر این کلاس رو از رنگ قبلی برمیداره و به رنگی که انتخاب کردیم میده.

و اما تغییر رنگ

colors.forEach(color => {
    color.addEventListener('click', handleColorChange)
})
const handleColorChange = (e) => {
    document.querySelector('.activeColor').classList.remove('activeColor')
    penColor = e.target.classList[1]
    e.target.classList.add('activeColor')
}

الان به جای اون صفحه خالی این رو داریم. البته باید “در ارتباط با سرور مشکلی به وجود امده است” رو هم بنویسیم:)

زییییییییییباست!

نوشته در ارتباط با سرور مشکلی به وجود آمده است. لطفا چند دقیقه نقاشی بکشید! اولین بار در ویرگول پدیدار شد.

گردآوری توسط ایده طلایی

دیدگاهتان را بنویسید