Первая статья в 2020, я был занят просмотром и чисткой вопросов в начале года и не было времени написать.Чем больше книг я читал, тем менее умелым себя чувствовал, и я всегда задерживался в рядах маленьких цыплят.В последнее время , в проекте есть дело с канвасом.Внезапно огонь на фронтенде моего UI снова загорелся, и я записал подводные камни и мысли 🤔.
Ступайте на яму 💥
Вопрос 1: Почему изображение на холсте размыто?
При рисовании изображений/текста на холсте мы устанавливаем ширину и высоту холста: 375*667, и мы обнаружим, что нарисованная картинка очень размыта, она похожа на картинку с плохим разрешением, а текст также будет выглядеть наложенным. фильм.
Примечание. Физический пиксель относится к наименьшей единице, отображаемой на экране мобильного телефона, а независимый от устройства пиксель (логический пиксель) — это точка в компьютерном устройстве, а пиксель, установленный в css, относится к пикселю.
Причина: во фронтенд-разработке мы знаем, что свойство называетсяdevicePixelRatio(设备像素比)
, который определяет, сколько (обычно 2) физических пикселей будет использоваться для рендеринга независимого от устройства пикселя при рендеринге интерфейса.
Например, изображение размером 100*100 пикселей на экране Retina будет использовать 2 пикселя для рендеринга одного пикселя изображения, что эквивалентно удвоению изображения, поэтому изображение станет размытым, что также является причина, по которой 1px утолщается на экранах сетчатки.
решить: Увеличьте ширину и высоту холста в 2 раза и уменьшите отображаемую ширину и высоту холста в 2 раза с помощью стиля. раз.
Например:
<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>
Вопрос 2: Как обрабатывать преобразование px и rpx?
rpx — это уникальная единица размера в апплете, которую можно адаптировать к ширине экрана, а на iphone6/iphonex 1rpx равен разным пикселям. Таким образом, очень вероятно, что отображение вашего холста будет несовместимо с разными мобильными телефонами.
Перед рисованием плаката, эскизы дизайна, которые мы получаем, обычно основаны на увеличенном в 2 раза изображении iphone6. И из решения предыдущей задачи мы знаем, что размер холста также в 2 раза больше, поэтому мы можем напрямую измерить эскиз дизайна изображения в 2 раза и напрямую нарисовать холст, и на размер нужно обратить внимание. rpxtoPx.
/**
*
* @param {*} rpx
* @param {*} int //是否变成整数
factor => 0.5 //iphone6
pixelRatio => 2 像素比
*/
toPx(rpx, int) {
if (int) {
return parseInt(rpx * this.factor * this.pixelRatio)
}
return rpx * this.factor * this.pixelRatio
}
Вопрос 3: Когда canvasContext.measureText вычисляет чистые числа, на мобильном телефоне это 0.
Предоставляется в апплетеthis.ctx.measureText(text).width
вычислить длину текста, но если вы все数字
Если это так, вы обнаружите, что API всегда рассчитывается как 0. Итак, наконец, используйте смоделированный метод MeasureText для вычисления длины текста.
measureText(text, fontSize = 10) {
text = String(text)
text = text.split('')
let width = 0
text.forEach(function(item) {
if (/[a-zA-Z]/.test(item)) {
width += 7
} else if (/[0-9]/.test(item)) {
width += 5.5
} else if (/\./.test(item)) {
width += 2.7
} else if (/-/.test(item)) {
width += 3.25
} else if (/[\u4e00-\u9fa5]/.test(item)) { // 中文匹配
width += 10
} else if (/\(|\)/.test(item)) {
width += 3.73
} else if (/\s/.test(item)) {
width += 2.5
} else if (/%/.test(item)) {
width += 8
} else {
width += 10
}
})
return width * fontSize / 10
}
Вопрос 4: Как обеспечить центральное отображение строки шрифтов? Сколько строк?
Если шрифт слишком длинный, он будет выходить за пределы холста, делая рисунок некрасивым....
Вы можете установить ширину и вычислить ширину текста в цикле, если она превышает, используйте подстроку, чтобы перехватить ее и добавить...
Вот и все.
let fillText=''
let width = 350
for (let i = 0; i <= text.length - 1; i++) { // 将文字转为数组,一行文字一个元素
fillText = fillText + text[i]
// 判断截断的位置
if (this.measureText(fillText, this.toPx(fontSize, true)) >= width) {
if (line === lineNum) {
if (i !== text.length - 1) {
fillText = fillText.substring(0, fillText.length - 1) + '...'
}
}
if (line <= lineNum) {
textArr.push(fillText)
}
fillText = ''
line++
} else {
if (line <= lineNum) {
if (i === text.length - 1) {
textArr.push(fillText)
}
}
}
}
Формула расчета показана в текстовой игре:
Центрирование можно использовать в канве (ширина канвы - ширина текста)/2 + x (x - смещение шрифта по оси x)
let w = this.measureText(text, this.toPx(fontSize, true))
this.ctx.fillText(text, this.toPx((this.canvas.width - w) / 2 + x), this.toPx(y + (lineHeight || fontSize) * index))
Вопрос 5: Как быть с сетевым графом в апплете?
Что касается использования сетевых картинок в небольших программах, таких как картинки на CDN, то необходимо перейти к WeChat для управления LRU, чтобы можно было сэкономить время загрузки, когда та же самая картинка будет отрисовываться позже. Итак, во-первых, вам нужно настроить легальное доменное имя файла загрузки в фоновом режиме апплета WeChat.Во-вторых, вы можете загрузить изображение заранее перед рисованием холста, дождаться загрузки изображения, а затем начать рисовать, чтобы избежать рисования проблемы с отказом.
Вопрос 6: Данные изображения base64 можно установить для рисования в среде IDE, но это бесполезно на реальной машине?
Сначала конвертируйте base64 вUint8ClampedArray
Формат. затем пройтиwx.canvasPutImageData(OBJECT, this)
Нарисуйте на холст, затем экспортируйте холст в виде изображения.
Вопрос 7: О wx.canvasToTempFilePath
После успешного нарисования Canvas вы можете напрямую вызвать этот метод для генерации изображения. Нет проблем на IDE, но сгенерированное изображение будет неполным на реальной машине. Вы можете использовать SettimeOut, чтобы решить эту проблему.
this.ctx.draw(false, () => {
setTimeout(() => {
Taro.canvasToTempFilePath({
canvasId: 'canvasid',
success: async(res) => {
this.props.onSavePoster(res.tempFilePath)//回调事件
// 清空画布
this.ctx.clearRect(0, 0, canvas_width, canvas_height)
},
fail: (err) => {
console.log(err)
}
}, this.$scope)
}, time)
})
Вопрос 8: О Canvascontext.font
размер шрифта не может использовать десятичные дроби Если часть размера шрифта в настройке шрифта содержит десятичные знаки, вся настройка шрифта будет недействительной.
Вопрос 9: Отрисовка шрифта смещена под Android?
Эта проблема возникает на телефонах Android, ios ведет себя нормально. Когда я впервые увидел эту проблему, я не мог понять, почему некоторые из них были нормальными, а некоторые сильно продвинулись вперед. Выяснилось позже на Androidthis.ctx.setTextAlign(textAlign)
По умолчанию это центр, поэтому это приводит к путанице, и это нормально после изменения налево.
Задача 10: Нарисуйте линейный график
Используйте холст, чтобы нарисовать простую линейную диаграмму, просто используйтеlineTo
а такжеmoveTo
Два API могут быть связаны точкой. использоватьcreateLinearGradient
Нарисуйте тени.
думаю 💡
Мысль 1: Ограничения создания плакатов с таблицей конфигурации json
Текущему поколению плакатов нужно только измерить размер в соответствии с эскизом дизайна, но процесс измерения по-прежнему очень громоздкий, и требуется ручная точная настройка там, где эскиза дизайна недостаточно. В будущем вы также можете использовать метод перетаскивания на веб-странице, чтобы завершить черновик дизайна, автоматически сгенерировать json и применить его к плакату апплета.
Мысль 2: Ограничения постеров, созданных бэкендом
Плакат был сгенерирован бэкенд-студентами в начале. Преимущество в том, что он не требует времени на рисование внешнего интерфейса, а также не нужно наступать на яму WeChat API. Интерфейс возвращается, чтобы получить URL-адрес, и его можно отображается, но эффект, создаваемый в бэкэнде, не очень хорош.
Мысль 3: Ограничения плакатов, генерируемых интерфейсом
При генерации постеров на фронтенде я обнаружил, что это занимает больше времени, включая локальную загрузку изображений и необходимость писать setTimeout для Android, чтобы обеспечить нормальную отрисовку. Различные проблемы с совместимостью, dpr мобильных телефонов, android и ios и прочие непрерывные пасхалки наступают вам на лысину~ хахахаха~
пасхальные яйца
Не можете нарисовать их все с последним фоновым изображением canvas-2d?
В процессе разработки холста в апплете всегда был слабый свет, напоминающий мне.
Я также пробовал последний canvas2d api, он действительно синхронизируется с веб-стороной, и метод записи также более плавный.В инструментах разработчика вроде все нормально, но при запуске на мобильном телефоне он отображает только половину ширина.Тест под разными моделями тоже одинаков.
Хорошо изменить его на исходный холст позже. . . Конкретной причины в сообществе WeChat пока не нашли, будем изучать в последующих итерациях и апгрейдах.