CANVAS для небольших программ

задняя часть внешний интерфейс WeChat Canvas

предисловие

Небольшим совместным доступом к программе можно поделиться только с друзьями или группами WeChat, но не в кругу друзей.

На этой неделе получил такой дурацкий запрос.В апплете нужно реализовать функцию обмена картинками. Разрешить пользователям отправлять изображения в Моменты или другие каналы.

Когда я впервые получил это требование, я чувствовал, что все в порядке, но не особо.Первое чувство было в том, что я хотел свалить вину на серверную часть и вызвать интерфейс, чтобы серверная часть передала URL-адрес, и интерфейс отвечал только за его отображение. ^_^

Конечно, такую ​​наивную идею в принципе невозможно реализовать, если вы столкнетесь с таким бэкендом, пожалуйста, дорожите им.

Ближе к делу, если внешний интерфейс выполняет эту функцию сам по себе, он должен использовать одну вещь, и это Canvas.

первое использование

Canvas не уникален для небольших программ, он также доступен в html5. Но я особо не пользуюсь. Всего два или два раза, один был, когда я делал мини-игры h5, а другой был очень близок к потребностям этого времени.Также нужно было поместить содержимое в div на холст и сгенерировать картинку, чтобы пользователи мог сохранить это.

Для меня не проблема следовать предыдущим идеям.Апплет сам по себе инкапсулирует набор API, но API, связанный с холстом, в основном такой же, как и обычный html, поэтому я повторю его снова в соответствии с предыдущим веб-методом.

открытым

Сначала напишите следующий код в нашем wxml

<canvas class="canvas" canvas-id="canvas"></canvas>

Чтобы установить размер холста, вы можете установить его непосредственно в теге холста в wxml или использовать wcss. Лично предпочитаю использовать wcss.

вот и делоcanvas-idЭто уникальный идентификатор в небольшой программе, и его можно найти во многих местах.

Затем начинаем писать js

// 这里的 canvas 就是之前在 wxml 里的 canvas-id
let ctx = wx.createCanvasContext('canvas')

第一个坑的地方来了,正常来 page 里用是一点没问题没有的,但是在组件里的话,画不了,就是显示不出来。

чек об оплатеДокументацияМожно найти следующее предложение

Создайте контекст рисования холста (укажите canvasId). В пользовательском компоненте второй параметр передается в экземпляр компонента, чтобы управлять компонентом.<canvas/>Совет компонента: вам нужно указать canvasId, контекст рисования действует только на соответствующий<canvas/>

Очевидно, мы можем изменить код на следующий

let ctx = wx.createCanvasContext('canvas', this)

Нарисуйте текст и изображения в соответствующей позиции

Конкретно как рисовать я не буду об этом говорить, просто начну говорить о яме.

в соответствующем месте

Да, это очень неприятный момент. Холст центрирован, и положение каждой точки отличается на разных размерах экрана. Нам нужно получить ширину и высоту экрана для расчета. (в основном ширина) Апплет предоставляет следующие аспекты, давайте получим некоторую информацию об устройстве.

wx.getSystemInfo({
  success: (res) => {
    this.setData({
      windowWidth: res.windowWidth,
      windowHeight: res.windowHeight,
    })
  }
})

Слово

Это худший момент

Глядя на стиль, заданный пользовательским интерфейсом, в середине будет двухстрочный текст.

Когда я впервые получил это, я чувствовал себя так легко. После подсчета количества символов в каждой строке не стоит сокращать два абзаца. Конечный результат действительно крут. Есть длинные и короткие, и их больше предела.

Это явно не соответствует нашим требованиям. И причина этой проблемы. Это потому, что наш контент представляет собой смесь китайского и английского языков: китайский занимает два символа, а английский — только один.lengthПри перехвате и китайский, и английский равны 1. Если это не чистый английский или чистый китайский, его можно выровнять. Как это решить? Код включен!

getContent(detail, length = 24, row = 2) {
  let len = 0
  let index = 0
  let content = []
  for (let i = 0; len < detail.length; i++) {
    // 若未定义则致为 ''
    if (!content[index]) content[index] = ''
    content[index] += detail[i]
    // 中文或者数字占两个长度
    if (detail.charCodeAt(i) > 127 || (detail.charCodeAt(i) >= 48 && detail.charCodeAt(i) <= 57)) {
      len += 2;
    } else {
      len++;
    }
    if (len >= length || (row - index == 1 && len >= length - 2)) {
      len = 0
      index++
    }
    if (index === row) break
  }
  return content
}

мы можем использоватьcharCodeAtДля получения charCode китайское слово выше 127 (пс. В ходе проверки выяснилось, что число также занимает две длины). Чтобы предотвратить будущие изменения в требованиях, я извлек этот кусок и написал метод. После этого просто передайте содержимое, количество слов в строке и количество строк в порядке.

картина

Есть две ямы

  1. Вы не можете использовать сетевые картинки напрямую, вы не можете рисовать их на реальной машине
  2. Углы скруглять нельзя, если картинка квадратная, то она не будет обработана.

использование веб-изображения

Поскольку мы не можем напрямую использовать сетевые изображения, давайте изменим образ мышления, загрузим изображения локально и отобразим их.

  1. Скачать веб-изображения
wx.getImageInfo({
  src: url,
  success: (res) => {
    // 下载成功 即可获取到本地路径
    console.log(res.path)
  }
})

Если вы используете это напрямую, вы обнаружите, что будут ошибки. Апплет составляет белый список изображений, которые можно загрузить. это должно быть小程序后台 > 设置 > 服务器域名 > downloadFile合法域名Установите здесь доменное имя сетевого образа.

PS Поскольку доменное имя должно быть https, и его можно изменять только пять раз в месяц, рекомендуется размещать сетевые образы, которые необходимо загрузить, на собственный https-сервер, а затем переходить на CDN или что-то в этом роде. .

  1. рисовать картинки

Далее аналогично рисованию локального образа

ctx.drawImage(res.path, left, top, width, height);

Обработка округления изображения (в этом примере показан круг, принцип тот же)

Общая идея состоит в том, чтобы нарисовать круглую область, затем нарисовать изображение в этой области и, наконец, объединить и перехватить, чтобы создать круглое изображение. Конкретный код выглядит следующим образом

drawImage(ctx, url, left, top, width, height) {
  // 保存当前环境的状态
  ctx.save();
  // 起始一条路径,或重置当前路径
  ctx.beginPath();
  // 画一个圆
  ctx.arc(width / 2 + left, height / 2 + top, width / 2, 0, Math.PI * 2, false);
  // 从原始画布剪切任意形状和尺寸的区域
  ctx.clip();
  wx.getImageInfo({
    src: url,
    success: (res) => {
      // 向画布上绘制图像
      ctx.drawImage(res.path, left, top, width, height);
      // 返回之前保存过的路径状态和属性
      ctx.restore();
      // 画出来
      ctx.draw();
    }
  })
},

Вы обнаружите, что загрузка изображений — это одношаговая асинхронная операция. Если есть только одно изображение, все в порядке. Если изображений несколько, это будет очень грязно. Мы можем использоватьPromiseОптимизация

drawImage(ctx, url, left, top, width, height) {
  ctx.save();
  ctx.beginPath();
  ctx.arc(width / 2 + left, height / 2 + top, width / 2, 0, Math.PI * 2, false);
  ctx.clip();
  return new Promise((resolve, reject) => {
    wx.getImageInfo({
      src: url,
      success: (res) => {
        ctx.drawImage(res.path, left, top, width, height);
        ctx.restore();
        resolve()
      },
      fail: (e) => {
        reject(e)
      }
    })
  })
},

Экспортировать содержимое указанной области текущего холста, чтобы сгенерировать картинку указанного размера, и вернуть путь к файлу.

Используйте WeChatcanvasToTempFilePath

savePic () {
  let that = this;
  let offset_left = (this.data.windowWidth - 303) / 2
  console.log('savePic')
  wx.canvasToTempFilePath({
    x: offset_left,
    y: 0,
    width: 303,
    height: 398,
    canvasId: 'canvas',
    success: function (res) {
      console.log(res.tempFilePath)
    },
    fail (e) {
      console.log(e)
    }
  }, this)
}

Предварительный просмотр/сохранение изображения

На предыдущем шаге мы сохранили содержимое холста для создания изображения. На самом деле есть два варианта.

  1. saveImageToPhotosAlbum, сохранить файл в альбом
  2. previewImageПредварительный просмотр изображения напрямую

На самом деле, оба метода в порядке, вы можете сделать соответствующий выбор на основе фактического спроса.

Я использовал при выбореpreviewImage, поскольку для этого не требуется авторизация пользователя, пользователь может напрямую отправить это изображение другу, не сохраняя изображение. Если вы хотите сохранить изображение, вы также можете сохранить его во время предварительного просмотра.

маленький смысл

Раньше я думала, что это то же самое, когда читала статью, но только когда написала, поняла, как тяжело было рожать. Может быть, так лучше, продолжайте усердно работать. Это моя третья статья о Наггетс

Первые две статьи таковы, при необходимости можно прочитать

Советы по заполнению ям небольшой программы для преобразования сетевых запросов РЕШЕНИЕ ПРОБЛЕМА Адаптации мобильных терминалов

Недавно я пишу DApp, основанный на публичной цепочке туманностей. Существует план поощрения на два месяца с мая по июль.Если вы разместите DApp, вы можете получить 110 NAS, что составляет около 6000 юаней, небольшой доход. Заинтересованные друзья могут пройти регистрацию.ссылка для регистрации

В первую неделю я отправил два DApp и столкнулся с некоторыми подводными камнями.На этой неделе я напишу учебник для новичков, чтобы помочь вам лучше разрабатывать DApps.