小程序 将canvas雷达图画入另一个canvas背景内 并下载保存

先生成雷达图 在将雷达图插入到另一个canvas背景内 最后实现下载
如果需要中间比较大 可以放弃均等方式 使用减法 先减去中间大小 其余部分局等

html:
<canvas class='radarCanvas' canvas-id='radarCanvas'></canvas>
<canvas canvas-id="myCanvas" class="canvasIs"/>

css:
.radarCanvas {
    margin: 0 auto 0;
    height: 460rpx;
}
.canvasIs {
    width: 1080px;
    height: 1643px;
    position: fixed;
    left: 9000px;
}

//初始化数据
// var numCount = 5; //元素个数
var sys = wx.getSystemInfoSync();
var windowWidth = sys.windowWidth;
var numSlot = 4; //一条线上的总节点数
var mW = windowWidth * 0.74; //Canvas的宽度
var mCenter = mW / 2; //中心点
// var mAngle = Math.PI * 2 / numCount; //角度
var mRadius = mCenter - 60; //半径(减去的值用于给绘制的文本留空间)
var mWs = windowWidth * 0.74;
var mH = windowWidth * 0.74;
const app = getApp()

Page({
    data: {
        chanelArray1: [],
        score: "", //总分数
        numCount: "", //元素个数
        mAngle: "", //角度
        width: wx.getSystemInfoSync().windowWidth * 0.74, //canvas 宽度
        text: "", //文本
        region: [], //雷达图背景颜色、分数颜色
        nickName: "100",
        img: "背景图片",
        radCtx: null, //雷达图canvas
    },
    onLoad: function(options) {
        let that = this;
        let q = app.q
        wx.setNavigationBarTitle({
            title: app.title,
        })
        wx.getSystemInfo({
            success: function (res) {
                if (res.model.search('iPhone X') != -1) {
                    that.setData({
                        isIphoneX: ["285","40","245"],
                    })
                }
            }
        })  
        wx.request({
            url: "https://kuso.xyz/dailyTest/index.php?s=1&opt=score",
            data: {
                q: q
            },
            method: 'POST',
            header: {
                // 注意将默认header改成
                'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
            },
            success: (res) => {
                let result = res.data;
                if (result.status) {
                    that.setData({
                        chanelArray1: ["日常", 44, "rgba(244, 61, 61, 1)"], //名称、分数、点颜色
                        score: "100",
                        numCount: "1",  //只是例子 自己写多少个
                        mAngle: Math.PI * 2 / result.scoreArr.length,
                        text: "我是谁",
                        region: result.region,
                        radCtx: wx.createCanvasContext("radarCanvas"),
                    })
                    //雷达图
                    that.drawRadar()
                    //先下载下来背景
                    wx.downloadFile({
                        url: that.data.img,
                        success: function(res) {
                            //console.log(res);
                            that.setData({
                                img: res.tempFilePath
                            });
                            that.canvasImg();
                        }
                    })
                }
            },
            fail: () => {
                return "系统异常,请重试!"
            }
        })
    },
    // 雷达图
    drawRadar: function() {
        var sourceData1 = this.data.chanelArray1

        //调用
        this.drawEdge() //画六边形
        //this.drawArcEdge() //画圆
        this.drawLinePoint()
        //设置数据
        this.drawRegion(sourceData1, this.data.region[0]) //第一个人的
        //设置文本数据
        this.drawTextCans(sourceData1)
        //设置节点
        this.drawCircle(sourceData1)
        //绘制分数
        this.drawPhoto(this.data.radCtx)
        //开始绘制
        this.data.radCtx.draw()
    },
    // 绘制边
    drawEdge: function() {
        this.data.radCtx.setStrokeStyle("#AECA9A")
        this.data.radCtx.setLineWidth(2) //设置线宽
        for (var i = 0; i < numSlot; i++) {
            //计算半径
            this.data.radCtx.beginPath()
            var rdius = mRadius / numSlot * (i + 1)
            var currentAngle = -Math.PI / 2; //正确角度
            //画线段
            for (var j = 0; j < this.data.numCount; j++) {
                //坐标
                var x = mCenter + rdius * Math.cos(currentAngle);
                var y = mCenter + rdius * Math.sin(currentAngle);
                currentAngle += this.data.mAngle //正确角度
                this.data.radCtx.lineTo(x, y);
            }
            this.data.radCtx.closePath()
            this.data.radCtx.stroke()
        }
    },
    // 绘制连接点
    drawLinePoint: function() {
        this.data.radCtx.beginPath();
        var currentAngle = -Math.PI / 2; //正确角度
        for (var k = 0; k < this.data.numCount; k++) {
            var x = mCenter + mRadius * Math.cos(currentAngle);
            var y = mCenter + mRadius * Math.sin(currentAngle);

            currentAngle += this.data.mAngle //正确角度
            this.data.radCtx.moveTo(mCenter, mCenter);
            this.data.radCtx.lineTo(x, y);
        }
        this.data.radCtx.stroke();
    },
    //绘制数据区域(数据和填充颜色)
    drawRegion: function(mData, color) {

        this.data.radCtx.beginPath();
        var currentAngle = -Math.PI / 2; //正确角度
        for (var m = 0; m < this.data.numCount; m++) {
            var x = mCenter + mRadius * Math.cos(currentAngle) * mData[m][1] / 100;
            var y = mCenter + mRadius * Math.sin(currentAngle) * mData[m][1] / 100;

            currentAngle += this.data.mAngle //正确角度
            this.data.radCtx.lineTo(x, y);
        }
        this.data.radCtx.closePath();
        this.data.radCtx.setFillStyle(color)
        this.data.radCtx.fill();
    },

    //绘制文字
    drawTextCans: function(mData) {
        var currentAngle = -Math.PI / 2; //正确角度
        this.data.radCtx.setFillStyle("rgba(54, 66, 88, 1)")
        this.data.radCtx.font = '12px cursive' //设置字体
        for (var n = 0; n < this.data.numCount; n++) {
            var x = mCenter + mRadius * Math.cos(currentAngle);
            var y = mCenter + mRadius * Math.sin(currentAngle);
            // this.data.radCtx.fillText(mData[n][0], x, y);
            //通过不同的位置,调整文本的显示位置
            if (currentAngle >= 0 && currentAngle <= Math.PI / 2) {
                this.data.radCtx.fillText(mData[n][0], x + 5, y + 5);
            } else if (currentAngle > Math.PI / 2 && currentAngle <= Math.PI) {
                this.data.radCtx.fillText(mData[n][0], x - this.data.radCtx.measureText(mData[n][0]).width - 7, y + 5);
            } else if (currentAngle > Math.PI && currentAngle <= Math.PI * 3 / 2) {
                this.data.radCtx.fillText(mData[n][0], x - this.data.radCtx.measureText(mData[n][0]).width - 5, y);
            } else {
                if (n == 0) {
                    this.data.radCtx.setTextAlign('center');
                    this.data.radCtx.fillText(mData[n][0], x, y - 5);
                } else {
                    this.data.radCtx.setTextAlign('left');
                    this.data.radCtx.fillText(mData[n][0], x + 7, y + 2);
                }
            }
            currentAngle += this.data.mAngle //正确角度

        }
        //this.data.radCtx.drawImage("https://cdn.kuso.xyz/dailyTest/healthy/img/health1.png", x - 32, y - 32, 32, 32);
    },
    //画点
    drawCircle: function(mData) {
        var r = 3; //设置节点小圆点的半径
        var currentAngle = -Math.PI / 2; //正确角度
        for (var i = 0; i < this.data.numCount; i++) {
            var x = mCenter + mRadius * Math.cos(currentAngle) * mData[i][1] / 100;
            var y = mCenter + mRadius * Math.sin(currentAngle) * mData[i][1] / 100;
            currentAngle += this.data.mAngle //正确角度
            this.data.radCtx.beginPath();
            this.data.radCtx.arc(x, y, r, 0, Math.PI * 2);
            this.data.radCtx.fillStyle = mData[i][2];
            this.data.radCtx.fill();
        }

    },
    //绘制中心分数
    drawPhoto: function(ctx) {
        var that = this;
        ctx.save();
        that.circleImg(ctx, that.data.score, mCenter, mCenter);
    },
    circleImg: function(ctx, text, x, y) {
        ctx.save();
        ctx.beginPath();
        var fontSize = mCenter / 3 * 1;
        //ctx.font = fontSize + 'px Microsoft Yahei';
        ctx.setFontSize(fontSize);
        ctx.setFillStyle("#000000");
        ctx.setTextAlign('center')
        ctx.setFillStyle(this.data.region[1])
        ctx.setTextBaseline('middle')
        ctx.fillText(text, x, y);
    },
    canvasImg() {
        const ctx = wx.createCanvasContext('myCanvas');
        const grd = ctx.createLinearGradient(0, 0, 0, 0); //创建了一个线性的渐变颜色 前两个参数起点横纵坐标,后两个参数终点横纵坐标
        grd.addColorStop(0, '#fff');
        grd.addColorStop(0, '#fff');
        ctx.setFillStyle(grd); //为创建的canvans上下文添充颜色  如果没有设置 fillStyle,默认颜色为 black。
        ctx.fillRect(0, 0, 300, 556);
        ctx.drawImage(this.data.img, 0, 0, 300, 556); //里面的参数无非就是图片放置的位置即图片的横纵坐标,图片的宽高
        //ctx.drawImage(this.data.radCtx, 0, 0, 300, 556); 
        ctx.setFillStyle("#F55160");
        ctx.font = 'normal bold 15px sans-serif';
        ctx.setTextAlign('center'); //是否居中显示,参考点画布中线
        ctx.setFillStyle("rgba(81,166,113,1)");
        ctx.fillText(this.data.nickName, 150, 123);
        let _this = this;
        wx.canvasToTempFilePath({  //这句是实现雷达图插入得重点
            x: 0,
            y: 0,
            width: 300, //画布宽高
            height: 250,
            destWidth: 544, //画布宽高*dpr 以iphone6为准
            destHeight: 420,
            canvasId: 'radarCanvas',
            success: function(res) {
                ctx.drawImage(res.tempFilePath, 40, 135, 220, 180);
                ctx.draw(true);
            }
        })
        ctx.draw();
    },
    saveImg() {
        wx.showLoading({
            title: '保存中...'
        })
        wx.canvasToTempFilePath({
            x: 0,
            y: 0,
            width: 300, //画布宽高
            height: 556,
            destWidth: 600, //画布宽高*dpr 以iphone6为准
            destHeight: 1112,
            canvasId: 'myCanvas',
            success: function(res) {
                //console.log(res.tempFilePath) //生成的临时图片路径
                wx.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success: function(res) {
                        //console.log(res);
                        wx.hideLoading();
                        wx.showToast({
                            title: '保存成功',
                        })
                    },
                    fail: function(err) {
                        if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
                            // 这边微信做过调整,必须要在按钮中触发,因此需要在弹框回调中进行调用
                            wx.showModal({
                                title: '提示',
                                content: '需要您授权保存相册',
                                showCancel: false,
                                success: modalSuccess => {
                                    wx.openSetting({
                                        success(settingdata) {
                                            //console.log("settingdata", settingdata)
                                            if (settingdata.authSetting['scope.writePhotosAlbum']) {
                                                wx.showModal({
                                                    title: '提示',
                                                    content: '获取权限成功,再次点击图片即可保存',
                                                    showCancel: false,
                                                })
                                            } else {
                                                wx.showModal({
                                                    title: '提示',
                                                    content: '获取权限失败,将无法保存到相册哦~',
                                                    showCancel: false,
                                                })
                                            }
                                        },
                                        fail(failData) {
                                            //console.log("failData", failData)
                                        },
                                        complete(finishData) {
                                            //console.log("finishData", finishData)
                                        }
                                    })
                                }
                            })
                        }
                    },
                    complete(res) {
                        wx.hideLoading()
                    }
                })
            }
        })
    },
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

℡╮荆棘鸟゛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值