” Почему никто уже не использовал это для этого? “
Привет всем,
Бьюсь об заклад, я не единственный, у кого есть такие мысли. Я был в сообществе веб -разработчиков уже почти 12 лет, и я обнаружил, что думаю об этом несколько раз.
Отказ от ответственности: мой письменный английский отстой, я пытаюсь улучшить, пожалуйста, будьте нежными
Каждый раз, когда появляется новая крупная веб -функция, например, Canvas или Webassembly, для меня неизбежно начинать Immagine всевозможные новые приложения, которые теперь возможны. Тогда (почти) никто из них не оживает. Возможно, они просто менее крутые, чем то, как они мне кажутся, но мне нечего было потерять, и я разработал один из них.
Если бы мне пришлось выбрать одну веб -функцию в качестве моей любимой, Canvas выиграл бы руки вниз.
ИМХО Это самая недооцененная функция, которую мы имеем сейчас, и с этой серией статей я хочу поделиться тем, что я придумал до сих пор, надеясь, что больше людей увидят потенциал Canvas, как и я.
Потому что для меня реальный потенциал в холсте – это не то, что мы, разработчики, можем показать пользователям через него, но то, что пользователи могут вернуть нам, используя его. Полон в сети в мобильную эпоху действительно может быть окончательным вводом для всего, что не является простым текстом, номером или логическим.
Моя цель – достичь самых реалистичных опыта рисования.
Спойлер:
Давайте начнем с нуля. Canvas, мы все знаем основы:
// canvas creation const myCanvas = document.createElement('canvas') const ctx = myCanvas.getContext('2d') myCanvas.width = 400 myCanvas.height = 150 container.appendChild(myCanvas) // rect ctx.fillStyle = 'rgb(255, 0, 0)' ctx.fillRect(10, 10, 100, 80) // circle ctx.beginPath() ctx.fillStyle = 'rgb(0, 0, 255)' ctx.lineJoin = 'round' ctx.lineCap = 'round' ctx.arc(200, 50, 40, 0, 2 * Math.PI, true) ctx.fill() // image ctx.drawImage(myImg, 280, 10, 80, 80)
Нам очень понадобятся эти основы, так почему бы не инкапсулировать их (с еще несколькими вариантами):
const drawSquare = (destinationContext, x, y, alpha, size, color, rotation = 0) => { const halfSize = size / 2 destinationContext.globalAlpha = alpha destinationContext.fillStyle = color if (rotation % 90) { destinationContext.translate(x, y) destinationContext.rotate(rotation) destinationContext.fillRect(-halfSize, -halfSize, size, size) destinationContext.rotate(-rotation) destinationContext.translate(-x, -y) } else { destinationContext.fillRect(x - halfSize, y - halfSize, size, size) } } const drawCircle = (destinationContext, x, y, alpha, size, color) => { destinationContext.beginPath() destinationContext.fillStyle = color destinationContext.globalAlpha = alpha destinationContext.lineJoin = 'round' destinationContext.lineCap = 'round' destinationContext.arc(x, y, size / 2, 0, 2 * Math.PI, true) destinationContext.fill() } const drawImage = (destinationContext, x, y, alpha, size, image, rotation = 0) => { const halfSize = size / 2 destinationContext.globalAlpha = alpha if (rotation % 360) { destinationContext.translate(x, y) destinationContext.rotate(rotation) destinationContext.drawImage(image, -halfSize, -halfSize, size, size) destinationContext.rotate(-rotation) destinationContext.translate(-x, -y) } else { destinationContext.drawImage(image, Math.round(x - halfSize), Math.round(y - halfSize), size, size) } }
А затем используйте это:
drawSquare(ctx, 50, 150, 0.5, 80, 'rgb(255, 0, 0)', 30) drawSquare(ctx, 110, 150, 0.7, 80, 'rgb(0, 255, 255)', -40) drawCircle(ctx, 200, 150, 0.9, 50, 'rgb(255, 0, 0)') drawCircle(ctx, 240, 150, 0.9, 60, 'rgb(255, 255, 0)') drawCircle(ctx, 270, 150, 0.9, 70, 'rgb(0, 255, 255)') drawImage(ctx, 350, 150, 0.6, 60, myImg, 45)
Обратите внимание, что я дал практически ту же подпись всем из них. Это будет очень полезно позже.
Итак, теперь мы готовы нарисовать что -то на экране на сенсорном вводе (Да Я использую сенсорный ввод в этом примере, он будет почти таким же с мышью вниз/перемещение).
const defaultToolSize = 20 const currentToolColor = 'rgb(255, 0, 0)' const handleTouch = (e) => { const x = e.touches[0].clientX - myCanvas.offsetLeft const y = e.touches[0].clientY - myCanvas.offsetTop const alpha = e.touches[0].force || 1 drawCircle(ctx, x, y, alpha, defaultToolSize, currentToolColor) } myCanvas.addEventListener('touchstart', handleTouch) myCanvas.addEventListener('touchmove', handleTouch)
Хорошо, это что -то. Мы уже можем увидеть скелет того, что станет нашей линией.
Что если бы мы адаптировали размер, основанный на давлении силы?
const defaultToolSize = 20 const sizeForceFactor = 2 const handleTouch = (e) => { const x = e.touches[0].clientX - myCanvas.offsetLeft const y = e.touches[0].clientY - myCanvas.offsetTop const force = e.touches[0].force || 1 const size = defaultToolSize + (defaultToolSize * force) drawCircle(ctx, x, y, force size, currentToolColor) }
А почему не адаптировать размер на основе скорости перемещения сенсорного движения?
const sizeSpeedFactor = 5 const speedFactorLengthUnit = 200 let lastTouch = { x: -1, y: -1, force: 0, } // a bit of math const round = (n, d = 0) => { const m = d ? Math.pow(10, d) : 1 return Math.round(n * m) / m } const getDistanceBetweenTwoPoints = (x1, y1, x2, y2, decimals = 0) => round(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), decimals) const handleTouch = (e) => { const x = e.touches[0].clientX - myCanvas.offsetLeft const y = e.touches[0].clientY - myCanvas.offsetTop const force = e.touches[0].force || 1 const distance = lastTouch.x >= 0 ? getDistanceBetweenTwoPoints(lastTouch.x, lastTouch.y, x, y) : 0 const size = defaultToolSize + (defaultToolSize * force) + (defaultToolSize * sizeSpeedFactor * Math.min(distance / speedFactorLengthUnit, 1)) drawCircle(ctx, x, y, force, size, currentToolColor) lastTouch = { x, y, force } }
Мы могли бы пойти дальше и использовать склонность стилуса, чтобы адаптировать размер и альфа, но пока этого достаточно. Я буду обращаться с этим в другой раз.
Начиная с этой простой точки, мы создадим реалистичную линию.
Это все сейчас, я действительно надеюсь, что эта тема может заинтересовать некоторых из вас. Я провел много времени, преследуя цель воспроизведения бумажного опыта в Интернете, и я надеюсь, что это может быть полезно в будущем.
Пожалуйста, оставьте комментарий, если вам нравится эта тема. Я был бы рад ответить.
Спасибо за ваше время! Увидимся в следующем посте
Оригинал: “https://dev.to/alessandrocipolletti/why-nobody-in-using-insert-your-favourite-feature-yet-drawing-on-a-canvas-part-1-2ib2”