小程序canvas大全,(圓弧角,畫圓,圖片短邊展示,多行省略,不影響佈局)

先上效果圖: 

 

 

wxml:

<view class='canvas-box'>
  <canvas canvas-id='canvas' style='width:{{windowW}}px;height:{{windowH}}px;' wx:if="{{hideCanvas}}"></canvas>
</view>

wxss:

.canvas-box{
  position: fixed;
  left: 10000px;
}

js: 

const { roundRect, roundImage, drawTextOverflow } = require("../../utils/util.js");
let rpx;  //寬度%比   適配手機寬度
let xh;  //高寬比     適配手機高度
page({
    data: {
    windowW: '',   //設備寬高
    windowH: '',  
    canvasQr: '',   //二維碼圖片
    canvasDetail: '', //詳情項目圖片地址
    clip_left: '',//左偏移值,
    clip_top: '', //上偏移值
    clip_width: '',//截取寬度,截取高度
    clip_height: '',
    hideCanvas:false,  //canvas的隱藏
    detailData: {},   //我的數據,自行改動
}

_downImg:function(e){
    wx.getSystemInfo({
      success: function(res) {
        rpx = res.windowWidth / 375;
        xh = res.windowHeight / res.windowWidth
        _this.setData({
          windowW: res.windowWidth,
          windowH: res.windowHeight,
          scrollerHeight: res.windowHeight - (res.windowWidth / 750) * 120
        })
      }
    });
    console.log(e)
    //這裏是我調的接口得到的動態圖片,你們根據自己要求去改
    this.wxFileImg(e.detail.codeUrl);
    wx.showLoading({
      title: '正在生成圖片中',
      mask: true
    })
    this.setData({
      hideCanvas:true,
    })
  },
  //網絡圖片轉臨時
  wxFileImg: function (codeUrl) {
    let _this = this;
    wx.downloadFile({
      url: codeUrl,
      success: function (resQrFile) {
        _this.setData({
          canvasQr: resQrFile.tempFilePath
        })
        wx.downloadFile({
          url: _this.data.detailData.logo,
          success: function (resDetailFile) {
            wx.getImageInfo({
              src: resDetailFile.tempFilePath,
              success(resDetailInfo) {
                let img_width = resDetailInfo.width,
                  img_height = resDetailInfo.height;
                //左偏移值,上偏移值,截取寬度,截取高度
                let clip_left, clip_top, clip_width, clip_height;

                clip_height = img_width ;
                if (clip_height > img_height) {
                  clip_height = img_height;
                  clip_width = clip_height;
                  clip_left = (img_width - clip_width) / 2;
                  clip_top = 0;
                } else {
                  clip_left = 0;
                  clip_top = (img_height - clip_height) / 2;
                  clip_width = img_width;
                }
                _this.setData({
                  canvasDetail: resDetailFile.tempFilePath,
                  clip_left,
                  clip_top,
                  clip_width,
                  clip_height
                })
                let canvas = wx.createCanvasContext('canvas');
                _this.canvasdraw(canvas);
              }
            })
          }
        })
      }
    })
  },
  canvasdraw: function (canvas) {
    let _this = this;
    let windowW = _this.data.windowW;
    let windowH = _this.data.windowH;
    let canvasQr = _this.data.canvasQr;
    let canvasDetail = _this.data.canvasDetail;
    let clip_left = _this.data.clip_left;
    let clip_top = _this.data.clip_top;
    let clip_width = _this.data.clip_width;
    let clip_height = _this.data.clip_height;
    let detailData = _this.data.detailData;

    // 整畫布
    canvas.setFillStyle('#EFEFEF');
    canvas.fillRect(0, 0, windowW, windowH);
    canvas.draw(true);
    // 主畫布
    console.log(xh)
    // 由於手機的高寬比不同,適配主畫布的高度,可以根據自己的畫布要求自行調整
    if (xh > 1.9) {
      roundRect(canvas, 15 * rpx, 100 * rpx, windowW * 0.92, windowH * 0.65, 10 * rpx, '#FFFFFF');
    } else if (xh > 1.8)  {
      roundRect(canvas, 15 * rpx, 80 * rpx, windowW * 0.92, windowH * 0.75, 10 * rpx, '#FFFFFF');
    }else{
      roundRect(canvas, 15 * rpx, 80 * rpx, windowW * 0.92, windowH * 0.8, 10 * rpx, '#FFFFFF');
    }

    //詳情圖片
    roundImage(canvas, 10 * rpx, canvasDetail, clip_left, clip_top, clip_width, clip_height, 15 * rpx, 30 * rpx, 345 * rpx, 245 * rpx, '#ffffff');
    //遮擋圖片圓角
    roundRect(canvas, 15 * rpx, 210 * rpx, windowW * 0.92, 90 * rpx, 10 * rpx, '#FFFFFF');
    // 項目名稱 2行展示
    drawTextOverflow(canvas, detailData.title, 305 * rpx, 2, 24, "#333", 28, 35 * rpx, 260 * rpx);

    // 項目價格
    canvas.setFontSize(20);
    canvas.fillStyle = "#DD2534";
    canvas.setTextAlign('left');
    //文字加粗
    canvas.fillText(detailData.priceText, 35 * rpx, 319.5 * rpx);
    canvas.fillText(detailData.priceText, 34.5 * rpx, 320 * rpx);
    // 項目區域
    canvas.setFontSize(16);
    canvas.fillStyle = "#666666";
    canvas.setTextAlign('left');
    canvas.fillText(detailData.district, 35 * rpx, 350 * rpx);

    // 項目面積
    canvas.setFontSize(16);
    canvas.fillStyle = "#666666";
    canvas.setTextAlign('left');
    canvas.fillText(detailData.landAreaText || detailData.houseSizeText, 35 * rpx, 380 * rpx);

    //二維碼
    canvas.drawImage(canvasQr, 35 * rpx, 410 * rpx, 100 * rpx, 100 * rpx);

    //名字
    canvas.setFontSize(16);
    canvas.fillStyle = "#333333";
    canvas.setTextAlign('left');
    canvas.fillText(detailData.userName, 155 * rpx, 445 * rpx);
    // 線
    canvas.beginPath();
    canvas.setLineWidth(0.1);
    canvas.setFillStyle('#EFEFEF');
    canvas.moveTo(155 * rpx, 460 * rpx);
    canvas.lineTo(325 * rpx, 460 * rpx);
    canvas.stroke();

    // 提示
    canvas.setFontSize(16);
    canvas.fillStyle = "#999999";
    canvas.setTextAlign('left');
    canvas.fillText('微信長按或掃一掃打開', 155 * rpx, 490 * rpx);
    canvas.draw(true, setTimeout(function () {
      _this.daochu()
    }, 1000));
  },

  //整個畫布圖片
  daochu: function () {
    let _this = this;
    let windowW = _this.data.windowW;
    let windowH = _this.data.windowH;
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: windowW,
      height: windowH,
      destWidth: windowW * 3,  //3倍像素  更清晰
      destHeight: windowH * 3,
      canvasId: 'canvas',
      success: function (res) {
        // console.log(res)
        wx.hideLoading();
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
          }
        })
        wx.previewImage({
          urls: [res.tempFilePath],
        })
        _this.setData({
          hideCanvas: false
        })
      },
      fail:function(err){
        wx.hideLoading();
        // console.log(err)
      }
    })
  },
})

 

 

 

util.js

/**
 * canvas繪製圓角矩形
 * @param {Object} context - canvas組件的繪圖上下文
 * @param {Number} x - 矩形的x座標
 * @param {Number} y - 矩形的y座標
 * @param {Number} w - 矩形的寬度
 * @param {Number} h - 矩形的高度
 * @param {Number} r - 矩形的圓角半徑
 * @param {String} [c = 'transparent'] - 矩形的填充色
 */
const roundRect = (context, x, y, w, h, r, c = 'transparent') => {
  if (w < 2 * r) {
    r = w / 2;
  }
  if (h < 2 * r) {
    r = h / 2;
  }
  context.beginPath();
  context.fillStyle = c;

  context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  context.moveTo(x + r, y);
  context.lineTo(x + w - r, y);
  context.lineTo(x + w, y + r);

  context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
  context.lineTo(x + w, y + h - r);
  context.lineTo(x + w - r, y + h);

  context.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
  context.lineTo(x + r, y + h);
  context.lineTo(x, y + h - r);

  context.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
  context.lineTo(x, y + r);
  context.lineTo(x + r, y);

  context.fill();
  context.closePath();
};


/**
 * canvas繪製圓角圖片
 * @param {Object} context - canvas組件的繪圖上下文
 * @param {Number} r - 圓角半徑
 * @param {String} path - 圖片地址
 * @param {Number} sx - 源圖像的矩形選擇框的左上角 x 座標
 * @param {Number} sy - 源圖像的矩形選擇框的左上角 y 座標
 * @param {Number} sWidth - 源圖像的矩形選擇框的寬度
 * @param {Number} sHeight - 源圖像的矩形選擇框的高度
 * @param {Number} dx - 圖像的左上角在目標 canvas 上 x 軸的位置
 * @param {Number} dy - 圖像的左上角在目標 canvas 上 y 軸的位置
 * @param {Number} dWidth - 在目標畫布上繪製圖像的寬度,允許對繪製的圖像進行縮放
 * @param {Number} dHeight - 在目標畫布上繪製圖像的高度,允許對繪製的圖像進行縮放
 * @param {String} c - 矩形的填充色
 */
const roundImage = (context, r, path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, c) => {
  context.save();
  roundRect(context, dx, dy, dWidth, dHeight, r, c);
  context.fill();
  context.clip();
  context.drawImage(path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
  context.restore();
};
/**
* 繪製圓形圖片
* @param {Object} context - canvas組件的繪圖上下文
* @param {String} path - 圖片地址
* @param {Number} x - 圖片的x座標
* @param {Number} y - 圖片的y座標
* @param {Number} r - 圖片的半徑
*/
const circleImage = (context, path, x, y, r) => {
  let d = 2 * r;
  let cx = x + r;
  let cy = y + r;

  context.save();
  context.beginPath();
  context.arc(cx, cy, r, 0, 2 * Math.PI);
  context.fill();
  context.clip();
  context.drawImage(path, x, y, d, d);
  context.restore();
};
/**
 * canvas多行文本溢出
 * @param {Object} context - canvas組件的繪圖上下文
 * @param {String} text - 文本內容
 * @param {Number} maxWidth - 文本最大寬度
 * @param {Number} maxRow - 文本最多顯示行數
 * @param {Number} fontSize - 字體樣式
 * @param {String} color - 文本顏色
 * @param {Number} lineHeight - 文本行高
 * @param {Number} x - 文本的x座標
 * @param {Number} y - 文本的y座標
 */
const drawTextOverflow = (context, text, maxWidth, maxRow, fontSize, color, lineHeight, x, y) => {
  let arr = [];
  let temp = '';
  let row = [];

  text = text.replace(/[\r\n]/g, ''); // 去除回車換行符
  arr = text.split('');
  context.setFontSize(fontSize);  // 注意:一定要先設置字號,否則會出現文本變形
  context.fillStyle = color;

  if (context.measureText(text).width <= maxWidth) {
    row.push(text);
  } else {
    for (let i = 0; i < arr.length; i++) {
      // 超出最大行數且字符有剩餘,添加...
      if (row.length == maxRow && i < arr.length - 1) {
        row[row.length - 1] += '...';
        break;
      }

      // 字符換行計算
      if (context.measureText(temp).width < maxWidth) {
        temp += arr[i];
        // 遍歷到最後一位字符
        if (i === arr.length - 1) {
          row.push(temp);
        }
      } else {
        i--;  // 防止字符丟失
        row.push(temp);
        temp = '';
      }
    }
  }
  // 繪製文本
  for (let i = 0; i < row.length; i++) {
    context.fillText(row[i], x, y + i * lineHeight, maxWidth);
  }
  return row.length * lineHeight;  // 返回文本高度
};

util轉載於https://www.jianshu.com/p/6c600e740194

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章