>  기사  >  위챗 애플릿  >  캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

hzc
hzc앞으로
2020-06-17 09:18:314692검색

2020년 첫 글입니다. 연초에 질문을 검토하고 답변하느라 바빠서 아무것도 쓸 시간이 없었습니다. , 내 프로젝트에 우연히 캔버스 사업이 있었는데 갑자기 UI 프런트엔드에 불이 붙었고, 함정과 생각을 적었습니다.

함정 속으로 들어가세요

질문 1: 캔버스에 그린 그림이 흐릿해지는 이유는 무엇인가요?

캔버스에 그림/텍스트를 그릴 때 캔버스의 너비와 높이를 375*667로 설정합니다. 그려진 그림이 매우 흐릿하고 해상도가 낮은 그림처럼 느껴지며 텍스트도 흐릿하게 보입니다. 겹치는 그림자가 있습니다.

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

참고: 물리적 픽셀은 휴대폰 화면에 표시되는 가장 작은 단위를 의미하고, 장치 독립 픽셀(논리 픽셀)은 컴퓨터 장치의 한 지점을 의미합니다. 픽셀.

이유: 프런트 엔드 개발에서는 인터페이스를 렌더링할 때 장치 독립적인 픽셀을 렌더링하는 데 사용되는 물리적 픽셀 수(보통 2개)를 결정하는 devicePixelRatio(设备像素比)라는 속성을 알고 있습니다.

예를 들어 100*100픽셀 사진의 경우 레티나 화면에서는 사진의 한 픽셀을 렌더링하는 데 2픽셀이 사용되며 이는 사진을 두 배로 늘리는 것과 동일하므로 이 역시 흐릿해집니다. 레티나 화면에서 1px가 두꺼워지는 이유.

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

해결책: 캔버스 너비와 캔버스 높이를 2배로 늘리고, 스타일을 통해 캔버스 표시 너비와 높이를 2배로 줄입니다. times.

예:

<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>

질문 2: px 및 rpx 변환을 어떻게 처리하나요?

rpx는 미니 프로그램의 고유한 크기 단위로, iPhone6/iphonex에서 1rpx는 다른 px와 같습니다. 따라서 캔버스 디스플레이가 다른 휴대폰에서 일관되지 않을 가능성이 있습니다.

포스터를 그리기 전 우리가 받는 디자인 초안은 대개 iPhone6의 2x 이미지를 기반으로 합니다. 그리고 이전 문제에 대한 해결 방법을 통해 캔버스의 크기도 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 메서드를 사용하여 텍스트 길이를 계산합니다. 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:如何保证一行字体的居中展示?多行呢?

字体的如果过长,会超出canvas画布,造成绘制难看,这个时候我们就应该让超出的部分变成...你可以设置一个width并且循环计算计算出文本的宽度,如果超出则利用substring截取后补充...即可。

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 = &#39;&#39;
          line++
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText)
            }
          }
        }
      }

文字剧中展示计算公式:

居中在canvas中可以用(canvas的宽度-文字宽度)/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上的图片,是需要down到微信本地进行 LRU 管理,让后续绘制同样图片时,节省下载时间。所以首先需要你在微信小程序的后台配置downloadFile合法域名,其次你可以在canvas绘制之前,最好提前去down图片,等待图片下载好了,再开始绘制,以避免一些绘制失败的问题。

问题6:在 IDE 中可设置 base64 的图片数据进行绘制,但真机上无用?

先把 base64 转成 Uint8ClampedArray 格式。然后再通过 wx.canvasPutImageData(OBJECT, this)

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)
    })

질문 4: 글꼴 줄이 중앙에 표시되도록 하려면 어떻게 해야 하나요? 몇 줄인가요?

글꼴이 너무 길면 캔버스를 초과하여 그림이 보기 흉해집니다. 이때 남는 부분을 ...로 설정해야 합니다. 너비와 루프 계산을 설정할 수 있습니다. 텍스트를 계산하려면 너비를 초과하는 경우 하위 문자열을 사용하여 ...를 가로채서 추가하세요.

rrreee

텍스트 재생에 표시된 계산 공식:

캔버스에서 센터링을 사용할 수 있습니다(캔버스 너비 - 텍스트 너비)/2 + x(x는 글꼴의 x축 이동)

rrreee질문 5: 미니 프로그램에서 네트워크 다이어그램을 처리하는 방법은 무엇입니까?

CDN의 이미지 등 미니 프로그램에서 네트워크 이미지를 사용하는 경우 로컬 LRU 관리를 위해 WeChat으로 내려가야 나중에 동일한 이미지를 그릴 때 다운로드 시간을 절약할 수 있습니다. 따라서 우선 위챗 애플릿의 백그라운드에서 downloadFile의 법적 도메인 이름을 구성해야 합니다. 둘째, 캔버스에 그리기 전에 이미지를 미리 다운로드하고 시작하기 전에 이미지가 다운로드될 때까지 기다리는 것이 가장 좋습니다. 그리기 실패 문제를 피하기 위해 그릴 수 있습니다.

질문 6: 그리기를 위해 IDE에서 Base64 이미지 데이터를 설정할 수 있지만 실제 머신에서는 쓸모가 없나요? 🎜먼저 base64를 Uint8ClampedArray 형식으로 변환하세요. 그런 다음 wx.canvasPutImageData(OBJECT, this)를 통해 캔버스에 그린 다음 캔버스를 그림으로 내보냅니다. 🎜🎜질문 6: 둥근 모서리 그림을 그리는 방법은 무엇인가요? 🎜🎜질문 7: wx.canvasToTempFilePath에 대하여🎜🎜 Canvas를 사용하여 성공적으로 그린 ​​후 이 메서드를 직접 호출하여 그림을 생성하면 IDE에서는 문제가 없지만 생성된 그림은 실제 컴퓨터에서는 불완전할 수 있습니다. 이 문제를 해결하기 위해. 🎜rrreee🎜질문 8: canvasContext.font 정보🎜🎜fontsize는 소수를 사용할 수 없습니다. 글꼴 설정의 글꼴 크기 부분에 소수점이 포함되어 있으면 전체 글꼴 설정이 무효화됩니다. 🎜

질문 9: Android에서 글꼴 렌더링이 잘못 정렬되나요?

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

이 문제는 Android 휴대폰에서 발생하며 iOS는 정상적으로 작동합니다. 이 문제를 처음 봤을 때 왜 일부는 중간에 있고 다른 일부는 훨씬 더 앞서 있는지 알 수 없었습니다. 나중에 확인해보니 Android에서 this.ctx.setTextAlign(textAlign)의 기본값이 center로 되어 있어 혼동을 주었는데 왼쪽으로 변경하니 정상이 되었습니다. this.ctx.setTextAlign(textAlign) 默认是为center,所以导致了错乱,改成left后就正常了。

问题10:绘制一个折线图

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

利用canvas绘制一个简单的折线图,只需要利用lineTomoveTo俩个API将点连接即可。利用createLinearGradient

질문 10: 꺾은선형 차트 그리기

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법

캔버스를 사용하여 간단한 선 차트를 그리려면 lineToAPI /code>와 moveTo의 점을 연결하세요. 그림자를 그리려면 createLinearGradient를 사용하세요. web端使用拖拽的方式去完成设计稿的事情,自动生成json

Thinking

Thinking 1: json 구성 테이블을 사용하여 포스터를 생성할 때의 한계

이제 포스터 생성은 디자인 시안에 따라 크기만 측정하면 되지만 디자인 시안이 충분하지 않을 경우 측정 과정이 여전히 매우 번거롭습니다. 일부 영역은 여전히 ​​수동으로 미세 조정해야 합니다. 나중에

를 만들어 미니프로그램 포스터에 적용할 수도 있습니다.

생각 2: 백엔드 생성 포스터의 한계

포스터는 처음에 백엔드 동급생이 생성합니다. 장점은 프런트 엔드 그리기 시간이 필요하지 않으며 WeChat의 함정에 빠질 필요가 없다는 것입니다. API. URL을 반환한 후 인터페이스가 표시될 수 있습니다. 그러나 백엔드에서 생성된 효과는 좋지 않습니다. 결국 이러한 종류의 작업은 프런트엔드에 가깝습니다.

생각 3: 프런트 엔드 포스터 생성의 한계

프런트 엔드에서 포스터를 생성할 때 이미지를 로컬로 다운로드하고 정상적인 그리기를 보장하기 위해 Android에 특별한 setTimeout을 요구하는 등 시간이 더 오래 걸린다는 것을 알았습니다. 다양한 호환성 문제, 휴대폰, 안드로이드, iOS의 DPR 등 논스톱 부활절 달걀이 대머리가 되겠네요~ 하하하하~

부활절 달걀캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법
최신 캔버스-2D 배경 이미지를 사용하면 정말 모든 것을 그리는 것이 불가능합니까?
캔버스를 개발하는 과정에서 항상 생각나게 하는 미니 프로그램에는 희미한 빛이 있었습니다.

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법
최신 canvas2d API도 사용해봤는데 실제로 웹측과 동기화가 되었고 작성 방법도 개발자 도구에서는 모든 것이 정상으로 보이지만 휴대폰에서 실행하면 절반만 실행됩니다. 다양한 모델에서 테스트할 때도 마찬가지입니다.

캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법
나중에 원본 캔버스로 바꾸시면 괜찮을 것 같아요. . . 구체적인 이유는 WeChat 커뮤니티에서 아직 발견되지 않았습니다. 후속 반복 및 업그레이드를 통해 연구하겠습니다.

🎜🎜🎜추천 튜토리얼: "🎜JS Tutorial🎜"🎜

위 내용은 캔버스를 사용하여 작은 프로그램에서 포스터를 그리는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제