Плакат мини-программы
GitHub.com/Джейсон Рид/Опасно…
нужно
Совместное использование апплета с кругом друзей может быть достигнуто только с помощью плаката с кодом апплета.Есть два способа сгенерировать код апплета, один — использовать внутренний метод, другой — использовать холст, который поставляется с апплет; разработан внутренний метод Это очень сложно, потому что генерация картинок потребляет много памяти, а также сильно нагружает сервер; поэтому использование холста апплета является хорошим выбором, но поскольку холст относительно глубокий, много ям, и есть разные плакаты, которые нужно воспроизводить Написание процесса рендеринга делает код избыточным и сложным в обслуживании.Кроме того, ситуация с разными версиями устройств разная.Поэтому необходимость Компоненты генерации небольших программных плакатов очень актуальны.
В реальной разработке я обнаружил, что элементы плаката представляют собой не что иное, как следующее: пока эти элементы реализованы, различные плакаты могут быть сгенерированы через файл конфигурации.
Классификация элементов в плакатах
проблема, которую нужно решить
-
единичная проблема
-
проблема с сокрытием холста
-
Прямоугольник со скругленными углами, изображение со скругленными углами
-
текст из нескольких абзацев
-
Проблемы с очень длинным текстом и сокращениями MText
-
Прямоугольник содержит текст
-
Иерархия между несколькими элементами
-
Несоответствие между размером изображения и размером рендеринга
-
холст к изображению
-
Проблема клипа IOS 6.6.7
-
О получении экземпляра холста
единичная проблема
Рисунок на холсте использует единицу измерения px, но необходимо преобразовать px разных устройств, поэтому единица rpx используется в компоненте единообразно, и здесь возникает вопрос, как преобразовать единицу измерения.
Получите размер экрана устройства через wx.getSystemInfoSync, чтобы получить соотношение, а затем выполните преобразование, код выглядит следующим образом:
const sysInfo = wx.getSystemInfoSync();
const screenWidth = sysInfo.screenWidth;
this.factor = screenWidth / 750; // 获取比例
function toPx(rpx) { // rpx转px
return rpx * this.factor;
}
function toRpx(px) { // px转rpx
return px / this.factor;
},
проблема с сокрытием холста
В процессе рисования плаката мы не хотим, чтобы пользователь видел холст, поэтому мы должны скрыть холст, первая мысль — использовать display:none; но это будет пустым при преобразовании в изображение, поэтому это не сработает, поэтому можно только управлять абсолютным позиционированием холста и перемещать его за пределы визуального интерфейса.Код выглядит следующим образом:
.canvas.pro {
position: absolute;
bottom: 0;
left: -9999rpx;
}
Прямоугольник со скругленными углами, изображение со скругленными углами
Поскольку холст не обеспечивает готовый закругленный API, мы можем только рисовать его вручную. На самом деле, округлый прямоугольник состоит из 4 линий (желтых) и 4 дуги (красных), следующим образом:
Дугу можно реализовать с помощью API canvasContext.arcTo Входной параметр этого API состоит из двух контрольных точек и радиуса, что соответствует примеру на рисунке выше.
canvasContext.arcTo(x1, y1, x2, y2, r)
Далее мы можем легко написать функцию для создания прямоугольника со скругленными углами.
/**
* 画圆角矩形
*/
_drawRadiusRect(x, y, w, h, r) {
const br = r / 2;
this.ctx.beginPath();
this.ctx.moveTo(this.toPx(x + br), this.toPx(y)); // 移动到左上角的点
this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y)); // 画上边的线
this.ctx.arcTo(this.toPx(x + w), this.toPx(y), this.toPx(x + w), this.toPx(y + br), this.toPx(br)); // 画右上角的弧
this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br)); // 画右边的线
this.ctx.arcTo(this.toPx(x + w), this.toPx(y + h), this.toPx(x + w - br), this.toPx(y + h), this.toPx(br)); // 画右下角的弧
this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h)); // 画下边的线
this.ctx.arcTo(this.toPx(x), this.toPx(y + h), this.toPx(x), this.toPx(y + h - br), this.toPx(br)); // 画左下角的弧
this.ctx.lineTo(this.toPx(x), this.toPx(y + br)); // 画左边的线
this.ctx.arcTo(this.toPx(x), this.toPx(y), this.toPx(x + br), this.toPx(y), this.toPx(br)); // 画左上角的弧
}
есликаркаспросто используйтеthis.ctx.stroke();
еслирисовать цветные блокипросто используйтеthis.ctx.fill();
еслиокруглое изображениепросто используйте
this.ctx.clip();
this.ctx.drawImage(***);
clip()метод вырезания любой формы и размера из оригинального холста. Как только область обрезана, все последующие рисунки ограничиваются обрезанной областью (нет доступа к другим областям на холсте). Вы можете сохранить текущую область холста с помощью метода save() перед использованием метода clip() и восстановить ее в любой момент позже (с помощью метода restore()).
текст из нескольких абзацев
Если есть несколько последовательных текстов в разных форматах, пользователю нереально указать координаты для каждого текста, потому что длина предыдущего текста не фиксирована.Решение здесь состоит в том, чтобы использоватьctx.measureText
(Начала поддерживать базовую библиотеку 1.9.90) Апи для расчета ширины куска текста, помните, что единица возвращаемой ширины - px(яма), чтобы узнать координаты следующего абзаца текста.
Проблемы с очень длинным текстом и сокращениями MText
Установите ширину текста наctx.measureText
Знайте ширину текста, если он превышает заданную ширину, использовать «...» для лишней части; для многострочного текста обнаружена, что высота шрифта примерно равна размеру шрифта, а также PARAMETER LINEHEIGHT предоставляется, чтобы пользователи настроить высоту строки, таким образом, мы знаем Y-координату следующей строки.
Прямоугольник содержит текст
Это также используетctx.measureText
интерфейс для управления шириной прямоугольника, конечно, пользователь также может установить поля paddingLeft и paddingRight;
Вертикальное центрирование текста может установить базовое выравнивание текста по середине (this.ctx.setTextBaseline('middle');
), установите координаты текста на центральную линию прямоугольника; отцентрируйте его по горизонталиthis.ctx.setTextAlign('center');
;
Иерархия между несколькими элементами
Поскольку у холста нет API для установки уровня элементов рисования, он может быть отрисован только в соответствии с тем, что более поздний уровень рисования выше, чем предыдущий рисунок, поэтому пользователю необходимо пройти в поле zIndex и использовать массив сортировка (Array.prototype.sort) для отрисовки по порядку.
Несоответствие между размером изображения и размером рендеринга
Для рисования используемctx.drawImage()
API;
При использованииdrawImage(dx, dy, dWidth, dHeight)
, изображение будет сжато, чтобы соответствовать нарисованному размеру, и изображение будет деформировано, как показано ниже:
Поддерживается начиная с базовой библиотеки 1.9.0drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
, sx и sy — координаты левого верхнего угла прямоугольной рамки выбора исходного изображения, sWidth и sHeight — ширина и высота прямоугольной рамки выбора исходного изображения, как показано ниже:
Если размер чертежа шире размера исходного изображения, то ширина размера чертежа равна ширине исходного изображения; в противном случае, если размер чертежа больше размера исходного изображения, высота размера чертежа равна равна высоте исходного изображения;
мы можем пройтиwx.getImageInfo
API получает размер исходного изображения;
холст к изображению
Вызывается после рисования холстаwx.canvasToTempFilePath
API преобразует холст в вывод изображения, поэтому вам нужно обратить внимание,wx.canvasToTempFilePath
нужно написать вthis.ctx.draw
в обратном вызове, и использование этого интерфейса в компоненте должно передать это во втором параметре (яма),следующим образом
this.ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'canvasid',
success: (res) => {
wx.hideLoading();
this.triggerEvent('success', res.tempFilePath);
},
fail: (err) => {
wx.hideLoading();
this.triggerEvent('fail', err);
}
}, this);
});
Проблема клипа IOS 6.6.7
В версии IOS 6.6.7, когда метод клипа постоянно обрезает картинки, действует только первая.Это баг WeChat, и официальное подтверждение (Developers.WeChat.QQ.com/community/…
О получении экземпляра холста
мы можем использоватьwx.createCanvasContext
Получите экземпляр апплета, но не забудьте использовать его в компоненте в качестве второго параметра, как показано ниже.
this.ctx = wx.createCanvasContext('canvasid', this);