123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- Component({
- properties: {
- painting: {
- type: Object,
- value: {view: []},
- observer (newVal, oldVal) {
- if (!this.data.isPainting) {
- if (newVal && newVal.width && newVal.height) {
- this.setData({
- showCanvas: true,
- isPainting: true
- })
- this.readyPigment()
- }
- }
- }
- }
- },
- data: {
- showCanvas: false,
- width: 100,
- height: 100,
- index: 0,
- imageList: [],
- tempFileList: [],
- isPainting: false
- },
- ctx: null,
- cache: {},
- ready () {
- wx.removeStorageSync('canvasdrawer_pic_cache')
- this.cache = wx.getStorageSync('canvasdrawer_pic_cache') || {}
- this.ctx = wx.createCanvasContext('canvasdrawer', this)
- },
- methods: {
- readyPigment () {
- const { width, height, views } = this.data.painting
- this.setData({
- width,
- height
- })
- const inter = setInterval(() => {
- if (this.ctx) {
- clearInterval(inter)
- this.ctx.clearActions()
- this.ctx.save()
- this.getImageList(views)
- this.downLoadImages(0)
- }
- }, 100)
- },
- getImageList (views) {
- const imageList = []
- for (let i = 0; i < views.length; i++) {
- if (views[i].type === 'image') {
- imageList.push(views[i].url)
- }
- }
- this.setData({
- imageList
- })
- },
- downLoadImages (index) {
- const { imageList, tempFileList } = this.data
- if (index < imageList.length) {
- this.getImageInfo(imageList[index]).then(file => {
- tempFileList.push(file)
- this.setData({
- tempFileList
- })
- this.downLoadImages(index + 1)
- })
- } else {
- this.startPainting()
- }
- },
- startPainting () {
- const { tempFileList, painting: { views } } = this.data
- for (let i = 0, imageIndex = 0; i < views.length; i++) {
- if (views[i].type === 'image') {
- this.drawImage({
- ...views[i],
- url: tempFileList[imageIndex]
- })
- imageIndex++
- } else if (views[i].type === 'text') {
- if (!this.ctx.measureText) {
- wx.showModal({
- title: '提示',
- content: '当前微信版本过低,无法使用 measureText 功能,请升级到最新微信版本后重试。'
- })
- this.triggerEvent('getImage', {errMsg: 'canvasdrawer:version too low'})
- return
- } else {
- this.drawText(views[i])
- }
- } else if (views[i].type === 'rect') {
- this.drawRect(views[i])
- }
- }
- this.ctx.draw(false, () => {
- wx.setStorageSync('canvasdrawer_pic_cache', this.cache)
- this.saveImageToLocal()
- })
- },
- drawImage (params) {
- this.ctx.save();
- const { url, top = 0, left = 0, width = 0, height = 0,borderRadius = 0, arcType = "", x = 0, y = 0, r = 0 } = params;
- if (borderRadius) {
- this.ctx.beginPath()
- if (arcType == "arc"){
- let borderRadiusLeft, borderRadiusRight, borderRadiusTop, borderRadiusBottom;
- if (borderRadius.toString().indexOf("/") != -1){
- let radiusArr = borderRadius.replace(/\s+/,"").split("/");
- borderRadiusTop = parseFloat(radiusArr[0]);
- borderRadiusRight = parseFloat(radiusArr[1]);
- borderRadiusLeft = parseFloat(radiusArr[2]);
- borderRadiusBottom = parseFloat(radiusArr[3]);
- }else{
- borderRadiusLeft = borderRadius, borderRadiusRight = borderRadius, borderRadiusTop = borderRadius, borderRadiusBottom = borderRadius;
- }
- // 绘制左上角圆弧
- this.ctx.arc(left + borderRadiusTop, top + borderRadiusTop, borderRadiusTop, Math.PI, Math.PI * 1.5);
- // 画一条线 x终点、y终点
- this.ctx.lineTo(left + width - borderRadiusTop, top);
- // 绘制右上角圆弧
- this.ctx.arc(left + width - borderRadiusRight, top + borderRadiusRight, borderRadiusRight, Math.PI * 1.5, Math.PI * 2);
- this.ctx.lineTo(left + width, top + height - borderRadiusRight);
- // 绘制右下角圆弧
- this.ctx.arc(left + width - borderRadiusBottom, top + height - borderRadiusBottom, borderRadiusBottom, 0, Math.PI * 0.5);
- this.ctx.lineTo(left + borderRadiusBottom, top + height);
- // 绘制左下角圆弧
- this.ctx.arc(left + borderRadiusLeft, top + height - borderRadiusLeft, borderRadiusLeft, Math.PI * 0.5, Math.PI);
- this.ctx.lineTo(left, top + borderRadiusLeft);
- }else{
- this.ctx.arc(left + borderRadius, top + borderRadius, borderRadius, 0, 2 * Math.PI)
- }
- this.ctx.clip();
- this.ctx.drawImage(url, left, top, width, height)
- } else {
- this.ctx.drawImage(url, left, top, width, height);
- }
- this.ctx.restore()
- },
- drawText (params) {
- this.ctx.save()
- const {
- MaxLineNumber = 2,
- breakWord = false,
- color = 'black',
- content = '',
- fontSize = 16,
- top = 0,
- left = 0,
- lineHeight = 20,
- textAlign = 'left',
- width,
- bolder = false,
- textDecoration = 'none'
- } = params
-
- this.ctx.beginPath()
- this.ctx.setTextBaseline('top')
- this.ctx.setTextAlign(textAlign)
- this.ctx.setFillStyle(color)
- this.ctx.setFontSize(fontSize)
- if (!breakWord) {
- this.ctx.fillText(content, left, top)
- this.drawTextLine(left, top, textDecoration, color, fontSize, content)
- } else {
- let fillText = ''
- let fillTop = top
- let lineNum = 1
- for (let i = 0; i < content.length; i++) {
- fillText += [content[i]]
- if (this.ctx.measureText(fillText).width > width) {
- if (lineNum === MaxLineNumber) {
- if (i !== content.length) {
- fillText = fillText.substring(0, fillText.length - 1) + '...'
- this.ctx.fillText(fillText, left, fillTop)
- this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
- fillText = ''
- break
- }
- }
- this.ctx.fillText(fillText, left, fillTop)
- this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
- fillText = ''
- fillTop += lineHeight
- lineNum ++
- }
- }
- this.ctx.fillText(fillText, left, fillTop)
- this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
- }
-
- this.ctx.restore()
- if (bolder) {
- this.drawText({
- ...params,
- left: left + 0.3,
- top: top + 0.3,
- bolder: false,
- textDecoration: 'none'
- })
- }
- },
- drawTextLine (left, top, textDecoration, color, fontSize, content) {
- if (textDecoration === 'underline') {
- this.drawRect({
- background: color,
- top: top + fontSize * 1.2,
- left: left - 1,
- width: this.ctx.measureText(content).width + 3,
- height: 1
- })
- } else if (textDecoration === 'line-through') {
- this.drawRect({
- background: color,
- top: top + fontSize * 0.6,
- left: left - 1,
- width: this.ctx.measureText(content).width + 3,
- height: 1
- })
- }
- },
- drawRect (params) {
- this.ctx.save()
- const { background, top = 0, left = 0, width = 0, height = 0 } = params
- this.ctx.setFillStyle(background)
- this.ctx.fillRect(left, top, width, height)
- this.ctx.restore()
- },
- getImageInfo (url) {
- return new Promise((resolve, reject) => {
- if (this.cache[url]) {
- resolve(this.cache[url])
- } else {
- const objExp = new RegExp(/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/)
- if (objExp.test(url)) {
- wx.getImageInfo({
- src: url,
- complete: res => {
- if (res.errMsg === 'getImageInfo:ok') {
- this.cache[url] = res.path
- resolve(res.path)
- } else {
- this.triggerEvent('getImage', {errMsg: 'canvasdrawer:download fail'})
- reject(new Error('getImageInfo fail'))
- }
- }
- })
- } else {
- this.cache[url] = url
- resolve(url)
- }
- }
- })
- },
- saveImageToLocal () {
- const { width, height } = this.data
- wx.canvasToTempFilePath({
- x: 0,
- y: 0,
- width,
- height,
- canvasId: 'canvasdrawer',
- complete: res => {
- if (res.errMsg === 'canvasToTempFilePath:ok') {
- this.setData({
- showCanvas: false,
- isPainting: false,
- imageList: [],
- tempFileList: []
- })
- this.triggerEvent('getImage', {tempFilePath: res.tempFilePath, errMsg: 'canvasdrawer:ok'})
- } else {
- this.triggerEvent('getImage', {errMsg: 'canvasdrawer:fail'})
- }
- }
- }, this)
- }
- }
- })
|