Далее я будуPure front-end реализует весь процесс создания плакатовЯ расскажу вам ясную и ясную идею.Я поделюсь и подробно объясню ямы, с которыми я столкнулся, чтобы вы не столкнулись с подобными проблемами.Даже если вы столкнетесь с проблемами, будет четкое направление, и рекомендуется, чтобы вы вырвали кровь.собиратьВолна, на крайний случай. (Вы не можете гарантировать будущие потребности, подобного нет, если есть, не забудьте поискать)
Дорога длинная, кто-то должен осмелиться сделать первый шаг в яме, я думаю, что я тот самый 😂😂, надеюсь, каждый сможет ступить на яму, которую я заполнил, рискуя таскать скорую помощь, ведущую к победе мини программа генерации плакатов дорога. Дарите розы, оставьте аромат в руке, друзья, которые читают, могут подарить авторуНравится, следуй за волнойОбновляйте суперсухие, суперхардкорные фронтенд статьи одну за другой.
одно написано впереди
1 Плакаты для рисования на холсте с QR-кодами. Всегда есть одна из этих ям, на которую вы можете наступить. Я проведу вас шаг за шагом, чтобы решить эти ямы
Предыстория технического отбора:taro3.0-vue
Начнем с одиннадцати вопросов.Я думаю, что в процессе рисования плакатов вы обязательно столкнетесь
Яма, с которой столкнулась структура Таро
① taro-vue createCanvasContext Недопустимая проблема с получением экземпляра холста, не удается отрисовать эффект? ✅
② Что я должен сделать, если Taro-Vue не может получить контекст холста во время инициализации и не могу нарисовать картинки вообще? ✅
Яма, с которой столкнулся холст апплета
③ Что касается ширины и высоты холста и коэффициента масштабирования, нарисованные элементы деформируются.Действительно ли высота холста равна ширине и высоте, установленным тегом cavans? ✅
④ Как холст рисует две сложенные вместе картинки и управляет уровнем? ✅
⑤ Как рисовать на холсте многострочный текст? ✅
⑥ Как точно восстановить положение каждого элемента плаката согласно дизайн-проекту. ✅
⑦ Как рисовать изображения base64 на холсте ✅
⑧ как нарисовать картинку сети два холста холст апи, нарисовать картинку В чем разница для завершения ✅
Создайте яму, обнаруженную QR-кодом
⑨ Как правильно выбрать и сгенерировать инструмент QR-кода? ✅
⑩ Что делать, если сгенерированный QR-код не распознается, ✅
⑪ Как нарисовать логотип на QR-коде✅
2 Достичь эффекта
2. Первый этап реального боя 1: инициализация холста апплета
1 Два способа для cavnas получить контекст
Проблемы, которые мы собираемся решить
① taro-vue createCanvasContext Недопустимая проблема с получением экземпляра холста, не удается отрисовать эффект?
② Что делать, если taro-vue не может получить контекст холста во время инициализации?
Официальный сайт WeChat представляет дваcanvas
Получить контекст, один старыйapi
, один новыйapi
, далее я объясню дваapi
Применение.
Метод createCanvasContext старой версии
createCanvasContext
Это приобретение, предоставленное WeChatcanvas
Старый интерфейс экземпляра используется следующим образом.
wxml
<canvas style="width: 300px; height: 200px;" canvas-id="firstCanvas"></canvas>
добрый день от написанияhello,world
Начинать.
js пишется так
onReady(){
/* 使用 wx.createContext 获取绘图上下文 context , firstCanvas 与 canvas 属性中的canvas-id一一对应 */
const context = wx.createCanvasContext('firstCanvas')
/* 设置字体大小 */
context.setFontSize(20)
/* 设置字体颜色 */
context.setFillStyle('pink')
/* 设置文本内容,位置 */
context.fillText('hello,world', 0, 0)
context.draw()
}
В старой версии использовалосьcreateCanvasContext
входящийcanvas
на этикеткеcanvas-id
свойства, чтобы получитьcanvas
Пример, старая версия используется, если честно, недостаточно гибкая, много парcanvas
Параметры линии и цвета инкапсулированы в методы, и методы необходимо вызывать каждый раз при их изменении.
Новая версия контекстально GetContext
Новый способ - сначала пройтиcreateSelectorQuery
Получатьcanvas
узел элемента, затем черезgetContext
Получить контекст.
wxml
<canvas type="2d" id="myCanvas"></canvas>
js
const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({
node: true,
size: true
})
.exec((res)=>{
const { node } = res[0]
if (!node) return
/* 获取 canvas 实例 */
const context = node.getContext('2d')
context.fillStyle = 'pink'
/* 设置字体样式 大小 字体类别 */
context.font = 'normal 400 12px PingFangSC-Regular',
context.fillText('hello,world', 0, 0)
})
таким образом и первыйcreateSelectorQuery
метод, будут тонкие различия в том, как используется API, это письмо больше похоже на нативныйDOM
Написание, установка цвета, стиля, прямое изменениеcontext
свойства вместо вызова соответствующегоapi
.
таро-вью использует холст
Решите проблему: ① taro-vue createCanvasContext недействителен для получения экземпляра холста, и эффект не может быть отрисован?
Поскольку наш выбор технологии апплетаtaro-vue2
, поэтому я сосредоточусь здесь наВ настоящее время в taro-vue createCanvasContext используется для получения экземпляров холста, и отрисовка холста никогда не была успешной.Даже если createCanvasContext может создавать контексты, ничего не может быть отрисовано (такие проходящие схемы пробовали снова и снова). Если вы спросите меня, почему? На самом деле, я тоже не знаю. Только студенты Bump Lab должны знать лучше. На GitHub также есть проблемы. Надеюсь, команда таро отнесется к этому серьезно.
Решение состоит в том, чтобы использовать последнююapi
, что является вторым решением, упомянутым выше. код показывает, как показано ниже:
import Taro from '@tarojs/taro'
const query = Taro.createSelectorQuery()
query.select('#myCanvas')
.fields({
node: true,
size: true
})
.exec(res=>{
//TODO:....
})
② Что делать, если taro-vue не может получить контекст холста во время инициализации?
В использованииtaro-vue
В процессе будет проблема, то есть проблема в том, что узел node апплета не может быть получен, это может быть вызвано жизненным циклом самого апплета и хаосом жизненного цикла vue. Особенно когда мы выбираем компоненты вместо страниц. Для таких случаев официальная документация дает ответ. Выполняется при первом отображении страницы.Этот жизненный цикл соответствует жизненному циклу onReady страницы апплета на стороне апплета. Начиная с этого жизненного цикла, доступ к реальному DOM можно получить с помощью таких API, как createCanvasContext или createselectorquery.
То есть, если вы хотите получитьdom
узел, мы можем сделать это,
компонент
mounted () {
eventCenter.once(getCurrentInstance().router.onReady, () => {
const query = Taro.createSelectorQuery()
query.select('#myCanvas')
.fields({
node: true,
size: true
})
.exec(res=>{
//TODO:....
})
})
}
К сожалению, эта ситуация иногда вызываетeventCenter.once()
Когда функция обратного вызова не выполняется, например, текущий компонент получаетv-if
ситуацию контролировать. Итак, как это решить, для этой ситуации я учу вас решению.
мы можем использоватьtaro
в, черезTaro.nextTick
метод, поставить задачу получить элемент в следующий разnextTick
воплощать в жизнь.
mounted(){
Taro.nextTick(() => {
// 获取元素
})
}
2 Инициализироватьcanvas
Установить ширину и высоту в процентах
Проблемы, которые мы собираемся решить:
③ Что касается ширины и высоты холста и коэффициента масштабирования, нарисованные элементы деформируются.Действительно ли высота холста равна ширине и высоте, установленным тегом cavans?
<template>
<view>
<canvas
id="myPoster"
type="2d"
class="canves"
:style="canvasStyle"
/>
</view>
</<template>
Здесь мы должны сначала понять два понятия,Ширина и высота контейнера: мы даемcanvas
Ширина и высота настройки метки такие же, как в приведенном выше коде.canvasStyle
,Даcanvas
Ширина и высота контейнера.Ширина и высота холста: И ширина и высота нашего холста, в новой версииapi
, получивnode
Узел, динамически устанавливаемыйnode.width
а такжеnode.height
ценность .
В качестве холста мы рассчитываем использовать весь экран, для разных мобильных телефонов размер экрана будет разным, поэтому нам нужно динамически получать ширину и высоту устройства. Здесь есть проблемаШирина и высота контейнера равны ширине и высоте холста?, ответ нет, почему вы так говорите, причины следующиеcanvas
Холст имеет примитивШирина и высота холста, и коэффициент масштабирования, и это с точки зрения одного пикселя, когда мы даемcanvas
настройки контейнераШирина и высота контейнераПосле этого, если нет соответствующей настройкиcanvas
холстШирина и высота холстатак же какscale
, нарисованный холст будет серьезно деформирован, поясняем на примере.
Например, мы хотим нарисовать картинку в верхней половине холста, когда ожидаем отрисовки нормального масштаба.canvas
, если мы только дадимcavans
Когда метка увеличивает ширину и высоту, не устанавливая ширину и высоту холста. Он будет нарисован в соответствии с соотношением сторон исходного холста.
Ожидаемый результат состоит в том, что холст заполняет экран, а изображения отображаются в нормальных пропорциях. когда мы не даемcavnas
Настройки холстаШирина и высота холстаИ при коэффициенте масштабирования. Происходит следующее.
фактический эффект:
Итак, когда мы инициализируем, нам нужно датьcanvas
Сделайте следующее. Об этом говорится в официальных документах WeChat.
import Taro, {
eventCenter,
getCurrentInstance
} from '@tarojs/taro'
export default {
name:'myPoster',
data(){
const {
windowHeight,
windowWidth,
pixelRatio
} = Taro.getSystemInfoSync() /* 动态获取设备的宽和高 */
return {
canvasStyle: { /* cavnas 的宽高 */
width: windowWidth + 'px',
height: windowHeight + 'px',
},
windowWidth,
pixelRatio, /* 屏幕缩放比 */
windowHeight,
scale:1
}
},
mounted(){
Taro.nextTick(() => {
const query = Taro.createSelectorQuery()
query.select('#myPoster').fields({
node: true,
size: true
}).exec(res => {
let {
node,
} = res[0]
if (!node) return
/* 第一步: canvas 画布的宽高 和 元素的宽高 必须保持相同的长宽比列,否则会变形 */
const dpr = this.pixelRatio
const context = node.getContext('2d')
node.width = windowWidth * dpr
node.height = windowHeight * dpr
context.scale(dpr, dpr)
context.fillStyle = '#fff'
context.fillRect(0, 0, windowWidth, windowHeight)
})
})
}
}
когда мы устанавливаемШирина и высота холста, а после коэффициента масштабирования его можно нарисовать в соответствии с нормальным коэффициентом. Давайте посмотрим на эффект изображения после установки коэффициента масштабирования, и он станет тем эффектом, который нам нужен.
Далее этап рисования.
3 Второй этап реального боя: этап рисования холста виртуальной точки
объяснениеcanvas
Перед тем, как сгенерировать плакат и идеально восстановить дизайн-проект, следует задуматься над вопросом, ведьcanvas
Холст, не в конце концовdom
модель, вы можете использоватьdiv
илиview
, путем пользовательской настройки стиля макета.cavnas
Нам нужно нарисовать эффект макета элементов.Здесь нам нужно точно получить значения x и y каждого элемента на холсте относительно холста. Итак, первое, что приходит на ум, это как получить точное значение x, y каждого элемента.
1 Виртуальная точка восстанавливает фактический эскиз проекта
Решать проблему:⑥ Как точно восстановить положение каждого элемента плаката согласно дизайн-проекту.Для задачи идеально восстановить осадку конструкции более надежное решение – нормально навесить в пропорции 1:1.dom
элемент, а затем нарисуйте его, получив позицию элементаcanvas
Позиция элемента холста. Мы используем картинку, чтобы проиллюстрировать принцип.
Меры предосторожности
Примечание 1: выберите правильный элемент, чтобы получить точку
Вот аналогия, мы находимся вdom
Такая структура может существовать внутри элемента.
<view class="box" >
<view class="parent" >
<view class="son" > 这里是将要绘制到canvas中的内容。 </view>
</view>
</view>
Для приведенной выше структуры нам нужно толькоson
Содержание в обращается кcanvas
В канве тогда возникает проблема, какой уровень информации об элементе мы хотим получить (left,top,width,height
), ответ должен быть в состоянии угадать, это должен быть ближайший слой контента, который вы хотите нарисовать, то есть поверхностьson
уровень. Если мы выберем внешний слой, мы можем получить родительский элементpadding
,margin
и другие воздействия, приводящие к неточному реальному местоположению.
Примечание 2. Старайтесь не добавлять элементы для получения информации.padding
marign
, если рисуете текстовое содержимое, попробуйте сделать высоту контейнера равной высоте текста
Также есть проблема, то есть старайтесь не добавлять больше элементов к элементам, которые нужно нарисовать.padding
marign
и другие свойства, если вы рисуете простой текст, не устанавливайтеlineHeight
, Как показано в примере:
Мы ожидаем получитьa
Информация о местоположении точки, но в конечном итоге получитьb
информация о местоположении точки. Если вы используетеb
указать, чтобы нарисоватьcanvas
, идеально восстановить проектный чертеж не получится, поэтому рисуем таким образомcanvas
следует обратить внимание на эти детали.
Инкапсулировать метод получения информации о местоположении
Нам нужно нарисовать каждую точку на плакате.Первое, что приходит в голову, это получить метод положения элемента апплета и инкапсулировать метод. мы используемpromise
Чтобы предотвратить глубокие обратные вызовы и прост в использованииasync await
Синтаксический сахар. Не много чепухи, ни слова о коде.
/* 获取元素位置 */
geDomPostion(dom, isAll) {
return new Promise((resolve) => {
Taro.createSelectorQuery().select(dom).boundingClientRect(rect => {
const {
top,
left
} = rect
/* isAll 是否获取设备宽高等信息 */
resolve(isAll ? rect : {
top,
left
})
}).exec()
})
},
намекать: при использованииwx
Нативные или другие межсетевые фреймворкиmpvue wepy uniapp
да одноклассник, поставьTaro
заменитьwx
Вот и все.
2 Рисование сетевых картинок
рисовать веб-картинки
Следующая задача, которую нам предстоит решить:⑨ Как рисовать изображения по сети, в чем разница между двумя способами рисования изображений через API холста?
мы используемcanvas
При рисовании изображения вы можете напрямую передать локальное изображениеcanvas
который предоставилdrawImage
Чтобы рисовать, а для сети картинки так рисовать нельзя, нам сначала нужно пройтиgetImageInfo
чтобы получить временный путь к изображению. использоватьgetImageInfo
При отрисовке сетевых ресурсов обратите внимание на настройку легального доменного имени загрузки, иначе мы не сможем успешно получить информацию об изображении. Сначала нам нужно настроить апплет в фоновом режимеdownloadFile
законное доменное имя.
Конкретные шаги заключаются в следующем: первый шаг:
Шаг 2:
третий шаг:
Следующее, что нам нужно сделать, это прочитать временный путь изображения и нарисовать его вcanvas
Подойдет холст.
/* backGroundImageUrl 是我们要画的网络图片的地址 */
this.getImageInfo(this.backGroundImageUrl).then(res=>{
const {
width, /* 宽度 */
height,
path /* 临时路径 */
} = res1
/* 第二步: 绘制banner图 */
const bannerImage = await this.geDomPostion('#bannerImage')
this.startTop = bannerImage.top - 30
this.drawImage(context, node, path, 0, 0, width, height, 0, this.startTop, windowWidth, windowWidth)
context.save()
})
this.drawImage
Это наш инкапсулированный метод.Как упоминалось ранее, для получения апплетаcontext
Два способа интерфейса, два способа рисованияcanvas
Картинки, есть некоторые отличия, сразу скажем.
Разница между новым и старым интерфейсом
Метод рисования старой версии
старая версия APIcreateCanvasContext
можно использовать напрямуюdrawImage
Рисовать картинки. следующим образом
/* 绘制图片 */
context.drawImage(url,x,y,width,height,dx,dy,dwidth,dheight)
В то время наш проект использовал второй новый API.getContext
В то время был получен контекст, поэтому способ рисования изображения будет изменен.
Метод рисования новой версии
const image = node.createImage()
image.src = url
image.onload = () => {
context.drawImage(image,x,y,width,height,dx,dy,dwidth,dheight)
}
Учащиеся, использующие новую версию API для рисования изображений, обратите внимание, что этоonload
Обратный вызов выполняется при загрузке изображения, поэтому описаниеАсинхронный. Есть еще один момент, на который следует обратить внимание по сравнению со старой версией.drawImage
Первый параметр — это путь к образу, а новая версияdrawImage
Первый параметрimage
элемент.
Инкапсулировать метод рисования изображений
Только что на последнем шаге рисования сетевой картинки мы назвалиthis.drawImage
метод. Потому что в течение всего процесса генерации плаката внутри будет отрисовываться несколько картинок, поэтому мы инкапсулируем метод для отрисовки картинок по отдельности.
/* 绘制图片 */
drawImage(context, node, url, ...arg) {
return new Promise((resolve) => {
const image = node.createImage()
image.src = url
image.onload = () => {
context.drawImage(image, ...arg)
resolve()
}
})
},
Так что мы можем пройти,async
,await
Определите, загружено ли изображение.
Введение context.drawImage
Я кратко познакомлю вас здесьcontext.drawImage
Применение,
CanvasContext.drawImage(imageResource / dom, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
Нарисуйте изображение на холсте, первый параметр представляет собой путь в старом API и представляет новую версию API.imagDom
элемент,
sx
нужно нарисовать на холсте,imageResource / dom
верхняя левая координата x прямоугольного (обрезанного) поля выбора
sy
нужно нарисовать на холсте,imageResource / dom
Y-координата левого верхнего угла прямоугольного (обрезанного) поля выбора.
sWidth
нужно нарисовать на холсте,imageResource / dom
ширина прямоугольного (обрезанного) поля выбора
sHeight
нужно нарисовать на холсте,imageResource / dom
высота прямоугольного (обрезанного) поля выбора
dx
Положение верхнего левого угла imageResource по оси x целевого холста.
dy
Положение верхнего левого угла imageResource по оси Y целевого холста.
dWidth
Ширина нарисованного imageResource на целевом холсте, позволяющая масштабировать нарисованный imageResource.
dHeight
Высота нарисованного imageResource на целевом холсте, позволяющая масштабировать нарисованный imageResource.
Мы используем график, чтобы представить, чему соответствует каждый атрибут.
3 Рисование многослойных картинок
Решать проблему:④ Как холст рисует две сложенные вместе картинки и управляет уровнем?
Если мы нарисуем две картинки, сложенные друг на друга, какую работу нам нужно сделать? Первое, что приходит к уму, это проблема уровня. Мы ожидаем, что фоновое изображение будет размещено ниже, например, такие изображения, как аватары, размещены на вершине, но в холсте нет контроля.zIndex
Иерархические свойства, так как решить эту проблему? Ответ на самом делеcanvas
в, нарисованопоследовательностьЭто порядок иерархии холста, верхний слой, который рисуется позже, рисуется первым, затем для такого рода иерархической задачи нам нужно только обеспечить, чтобы элементы с более высокими уровнями рисовались позже, а элементы с более низкими уровнями. Сначала нарисуйте, что можно отлично решить.Далее, в плакате, нарисуйте картинки, текст и другую информацию.
<!-- 头像区 -->
<image class="userheadImage" id="userheadImage" :src="headImage" />
/*TODO: 绘制头像 */
const userheadImage = await this.geDomPostion('#userheadImage',true)
/* 圆形图片 */
let d = userheadImage.height / 2
const cx = userheadImage.left + userheadImage.width / 2
let cy = userheadImage.top + userheadImage.height / 2
context.arc(cx, cy, d, 0, 2 * Math.PI)
context.strokeStyle = '#FFFFFF'
context.stroke()
context.clip()
await this.drawImage(context, node, this.headImage, userheadImage.left, userheadImage.top, userheadImage.width, userheadImage.height)
context.restore()
this.drawText(context,{ top: userheadImage.top + userheadImage.height + 40 ,left : userheadImage.left - 70 },'我不是外星人「前端Sharing」',18,'normal 600 20px PingFangSC-Regular','#fff')
в нашем использованииcontext.clip()
После этого не забудьте использоватьcontext.restore()
Сбросить, иначе никакие другие элементы не будут отрисовываться.
Эффект:
Мы прекрасно решили проблему уровня текста, теперь будем рисовать основное содержание постера. Когда мы рисуем плакаты, мы можем столкнуться с многострочным текстом, так много пар многострочного текста, как нам решить эту проблему?
4 Рисование многострочного текста
Решать проблему:⑤ Как рисовать на холсте многострочный текст?
canvas
нарисованный текст, не похожий на нашdom
Как и текст под элементом, он может автоматически переноситься, как восстановить эффект многострочного текста? Вот способ научить вас,Мы можем рисовать слово за словомcanvas
, а затем добавьте ширину каждого слова. Если общая ширина больше ширины контейнера, начните новую строку, увеличьте высоту каждой строки и начните с начала., переходим непосредственно к коду.
/** 画多行文本
* @param ctx canvas 上下文
* @param str 多行文本
* @param initHeight 容器初始 top值
* @param initWidth 容器初始 left值
* @param canvasWidth 容器宽度
*/
drawRanksTexts(ctx, str, initHeight, initWidth, canvasWidth) {
let lineWidth = 0;
let lastSubStrIndex = 0;
/* 设置文字样式 */
ctx.fillStyle = "#303133"
ctx.font = 'normal 400 15px PingFangSC-Regular'
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width
if (lineWidth > canvasWidth) { /* 换行 */
ctx.fillText(str.substring(lastSubStrIndex, i), initWidth, initHeight)
initHeight += 20
lineWidth = 0
lastSubStrIndex = i
}
if (i == str.length - 1) { /* 无需换行 */
ctx.fillText(str.substring(lastSubStrIndex, i + 1), initWidth, initHeight)
}
}
},
передача
/* TODO: 复制多行文本 */
const rowsText = await this.geDomPostion('#context', true)
this.drawRanksTexts(context, this.skuName, rowsText.top, rowsText.left, rowsText.width)
Эффект
4. Третий этап реального боя: Генерация QR-кода
Следующее что делаем рисуем QR код, процесс рисования QR кода автор наступил на много ям, особенноtaro-vue
не поддерживаетсяcreateCanvasContext
Я надеюсь, что смогу использовать яму, на которую я ступил, чтобы позволить всем избежать тех же ошибок и избежать многих окольных путей. Рисование двумерного кода на самом деле не так сложно, как можно себе представить.На самом деле, это преобразование ссылки в двумерный код, чтобы мобильный телефон мог сканировать код или долго нажимать, чтобы распознать его.Хотя принцип очень просто, есть еще много деталей, на которые нужно обратить внимание.
Нанесение QR-кода ничем не отличается от двух способов,Первый способ заключается в использованииcanvas
Нарисуй это. Второй преобразует ссылку вbase64
, затем позвольте изображению показать ссылку.Далее проведем технический подбор библиотеки двумерного кода для этих двух методов.
1 О выборе библиотеки QR-кодов
Решать проблему⑨ Как правильно выбрать и сгенерировать инструмент QR-кода?
В процессе формирования QR-кода мы не должны использовать алгоритм вручную, потому что даже если мы сможем сделать это вручную, это займет много времени, и будет многоbug
, потому что сейчас экология генерации QR-кодов очень здоровая, напримерqrcode.js
И так все очень хорошо, но плохо только то, что апплет не поддерживается. Здесь я представляю несколько библиотек QR-кода
weapp-qrcode
Например, для коротких ссылок, например, GitHub автора.GitHub.com/удачи Али…или Дом НаггетсТалант /user/241858…Такого рода все относятся к коротким ссылкам, вам не нужно писать очень длинные параметры, в этом случае используйтеweapp-qrcode
Более, чем достаточно. Этот метод основан на первомcanvas
нарисовано. И он использует старую версию API, поэтому есть проблема, если вы используете новую версию.getContext
образом, вам нужно загрузить исходный код, а затем изменить исходный код, чтобы он поддерживалgetContext
Сюда. Давайте представим weapp-qrcode
использование.
использовать
// 将 dist 目录下,weapp.qrcode.esm.js 复制到项目目录中 如果用 taro uniapp 等框架 ,可以用 npm install
import drawQrcode from '../../utils/weapp.qrcode.esm.js'
drawQrcode({
width: 200,
height: 200,
canvasId: 'myQrcode',
// ctx: wx.createCanvasContext('myQrcode'),
text: 'https://juejin.cn/user/2418581313687390',
// v1.0.0+版本支持在二维码上绘制图片
image: {
imageResource: '../../images/icon.png',
dx: 70,
dy: 70,
dWidth: 60,
dHeight: 60
}
})
результат
Таким образом, это, наконец, удалось, потому что выполнениеdemo
, Я используюgithub
Короткая ссылка. Но как только я вернулся к проекту компании автора, ссылка была очень длинной, а сгенерированный QR-код был настолько плотным, что мобильник вообще не мог его распознать, мне ничего не оставалось, как перейти на другие технические решения, поэтому автор выбрал второй, более устойчивый путь, для формированияbase64
документ.
qrcode-base64
qrcode-base64
это преобразовать ссылку QR-код вbase64
Ссылка и эта ссылка какsrc
Свойство присваивается изображению. Давайте сначала представим основное использование.
скачать
npm install qrcode-base64
использовать
import QR from 'qrcode-base64'
var imgData = QR.drawImg(this.data.codeText, {
typeNumber: 4,
errorCorrectLevel: 'M',
size: 500
})
// 返回输出base64编码imgData
Как показано в приведенном выше блоке кода,imgData
генерируетсяbase64
ссылка, мы можем напрямую использовать ее как изображениеsrc
, тогда пустьcanvas
Рисуем картинку в наш постер, но есть другая проблема,canvas
не поддерживает рисованиеbase64
Ссылка на изображение не влияет на реальную машину, за один шаг есть десять ям, мы должны найти способ решить эту проблему.
2 изображения на холсте base64
Решать проблему⑦ Как рисовать изображения base64 на холсте
для вышеупомянутогоcanvas
не поддерживаетсяbase64
изображение, то нам также нужно нарисовать QR-код на плакате, так что это не невозможно, мы можем использовать файловую систему, предоставляемую апплетом, для решения проблемы.
файловая система апплета
wx.getFileSystemManager
Получить глобально уникальный файловый менеджер, возвращаемое значение похоже наnode
в фс.
writeFile
Записывайте файлы, вы можете записывать картинки в систему.
const fs = wx.getFileSystemManager()
fs.writeFile(/* 写入文件 */)
Способ упаковки
Инкапсулировать метод рисования QR-кода
/* 生成二维码 */
drawCode(ctx, node, x, y) {
return new Promise((resolve) => {
const codeImageWidth = 150 /* 绘制二维码宽度 */
const canvasImageWidth = 85 /* 二维码绘制到canvas的宽度 */
const left = x - 15 /* left 值 */
const top = y - 22 /* top 值 */
const LogoWidth = 15 /* 二维码logo宽度 */
const url = 'https://juejin.cn/user/2418581313687390'
const base64 = QR.drawImg(url, {
typeNumber: 4,
errorCorrectLevel: 'L',
size: codeImageWidth
})
/* 创建读写流 */
const fs = Taro.getFileSystemManager()
const times = new Date().getTime()
const codeimg = Taro.env.USER_DATA_PATH + '/' + times + '.png'
/* 将base64图片写入 */
fs.writeFile({
filePath: codeimg,
data: base64.slice(22), /* 数据流 */
encoding: 'base64',
success: async () => {
const offset = (canvasImageWidth - LogoWidth) / 2 /* 偏移量 */
/* 绘制图片 */
await this.drawImage(ctx, node, codeimg, 0, 0, codeImageWidth, codeImageWidth, left, top, canvasImageWidth, canvasImageWidth)
await this.drawImage(ctx, node, this.logoUrl, left + offset, top + offset, LogoWidth, LogoWidth)
resolve()
}
})
})
},
Как показано выше, мы завершили отрисовку QR-кода. Давайте посмотрим, как его использовать.
использовать
мы вwxml
Напишите на нем элемент в качестве заполнителя, чтобы мы могли получить расположение QR-кода.
<view id="qrCode" class="store-uscode" />
/*TODO: 第四步:绘制二维码 */
const qrCode = await this.geDomPostion('#qrCode')
await this.drawCode(context, node, qrCode.left - 20, qrCode.top - this.cavnsOffsetop)
Эффект
Сканирование прошло успешно
3 Отладка размера QR-кода, как сделать QR-код узнаваемым и нарисовать логотип QR-кода
Решать проблему:⑩ Что делать, если сгенерированный QR-код не распознается.
Иногда, когда QR-код, который мы показываем, относительно мал, из-за того, что цветные блоки слишком плотные, мобильный телефон не сможет его распознать. тогда мыКак настроить QR-код, чтобы страница максимально точно восстанавливала эскиз дизайна?, вот небольшая хитрость для вас, вы можете сначала перейти на веб-сайт генерации QR-кода, сначала адаптироваться к наилучшему соотношению, которое может распознать мобильный телефон, и избежать ситуации, которая не может быть распознана. Рекомендуемый веб-сайт:Кормовой QR-код: https://cli.im/
Мы можем отладить пиксели QR-кода и размер логотипа онлайн, пока не будет настроен оптимальный размер дизайна.
Настройте QR-код онлайн
тонкая настройка Иногда нам нужно сделать точную настройку размера QR-кода, я предлагаю здесь на этапе отладки установитьпостоянныйконтролировать и корректировать хорошо написаноМетод регулировкиилиформула. Преимущество этого заключается в том, что всякий раз, когда мы делаем небольшую корректировку, это не повлияет на пересчет из-за текущей корректировки, как показано ниже.
const codeImageWidth = 150 /* 绘制二维码宽度 */
const canvasImageWidth = 85 /* 二维码绘制到canvas的宽度 */
const left = x - 15 /* left 值 */
const top = y - 22 /* top 值 */
const LogoWidth = 15 /* 二维码logo宽度 */
const offset = (canvasImageWidth - LogoWidth) / 2 /* 偏移量 */
4 Когда все будет готово, сгенерируйте постер и отправьте его друзьям
Мы запустили весь процесс. Последним шагом является создание изображения плаката и пересылка изображения. Вы можете использовать апплет WeChat для создания плакатовcanvas
серединаcanvasToTempFilePath
Создайте путь к изображению, а затем передайтеpreviewImage
Метод просмотра изображений, при просмотре изображений вы можете активировать функцию обмена друзьями апплета WeChat. Здесь есть одна вещь, на которую мы должны обратить внимание, это перехватcanvas
Эффективная высота.
Над кодом:
/* 生成海报 */
makePc(node) {
const {
startTop, /* 截取canvas画布的顶部 */
endTop, /* 截取canvas画布的底部 */
windowWidth /* 屏幕宽度 */
} = this
const _this = this
Taro.canvasToTempFilePath({
x: 0,
y: startTop,
width: windowWidth,
height: endTop - startTop,
destWidth: windowWidth * 3,
destHeight: (endTop - startTop) * 3,
canvas: node,
success: function (res) {
Taro.hideLoading()
Taro.previewImage({
urls: [res.tempFilePath]
})
}
})
}
CanvasToTempFilePath соображения
Или вернуться к исходному вопросу, при звонкеcanvasToTempFilePath
При вызове метода параметры, передаваемые старым и новым API, различаются.
В старых версиях API черезcreateCanvasContext
Рисунокcanvas
,canvasToTempFilePath
свойства конфигурацииcanvas
, документация для разработчиков WeChat объясняет это такcanvas
Идентификатор холста, переданныйcanvas
Экземпляр компонента (используйте это свойство, когда тип холста = "2d"), т. е.canvas
контекстcontext
.
Но мы используем новую версию,getContext
способ рисованияcanvas
, когда мы переходим вcontext
, не влияет, что?Есть такая штука, проблема с документацией разработчика WeChat? Позднее было обнаружено, что таким образом поступающий query.select
приобретенныйcanvas
изnode
Узлы действительно много ям~~~. Выйдет глоток старой крови.
5 Обзор эффектов
5 Резюме
При выполнении этой функции я действительно столкнулся с большим количеством ям, и даже было чувство, что хочется плакать без слез, но, наступив на ямы и пройдя весь путь, я действительно многое приобрел.
адрес проекта
Выкладываю весь процесс создания плакатаdemo
проект, загрузитьgithub
, Заинтересованные студенты, можете посмотреть, особенно те, кто выполняет эту функцию, приходите~
Адрес проекта, пожалуйста, нажмите здесь
новый год
В новом году я желаю вам удачи в новом году и желаю, чтобы сообщество Nuggets становилось все лучше и лучше.