微信小程序canvas画价格走势图(三)

今天继续更新在微信小程序上用canvas画价格走势图。上一篇讲了图上主要的部分,也就是折线图的绘制。假如我在我的绘图主函数中只调用了绘制折线图的函数,效果是这样的:

可以说除了作为坐标背景的<image>和折线图本身,这个图显得空落落的。现在我们来在这个图上绘制拐点

一、绘制出每个拐点的小圆

我们都可以很明显地看到折线图上的拐点,现在我们在拐点处绘制小圆,让拐点变得更明显

首先,要回答一个问题——怎么才能知道拐点的坐标?显然,拐点坐标并不是一开始就能得到的,而是绘制折线图的过程中计算出来的所以我在绘制折线图里的函数中收集拐点,折线图画完后,拐点信息也收集完了,最后把拐点信息返回给主函数。所以,我们现在主函数调用完绘制折线图的函数,就能从返回值中获取拐点数据了。可以像我这样:

 /**
     * 这个是绘图的主函数
     * @param {*} arr 每个值组成的数组
     * @param {*} xLeft 折线图最左边与画布边界的距离,单位是px,默认为0
     * @param {*} xRight 折线图最右边与画布边界的距离,单位是px,默认为0
     * @param {*} yBottom 折线图最下边与画布边界的距离,单位是px,默认为0
     * @param {*} yTop 折线图最上边与画布边界的距离,单位是px,默认为0
     * @param {*} specialIndex 特殊点的下标,默认为-1(默认没有特殊点)
     */
    function draw(arr, xLeft = 0, xRight = 0, yBottom = 0, yTop = 0, specialIndex = -1) {
      // 获取上下文对象
      const context = wx.createCanvasContext('canvas');
      // 获取画布的宽高
      const width = _this.data.canvasWidth;
      const height = _this.data.canvasHeight;
      // 记录图形的边界
      const borderInfo = { xLeft, xRight, yBottom, yTop }
      // 1.画折线图,传入数据,主色调,画布宽高,图形边界和特殊点位置
      // 获得返回的拐点数组
      const pointArray = drawFoldLine(context, arr, mainColor, width, height, borderInfo, specialIndex)
      // 主函数的其他代码...
    }

接下来就比较简单了,遍历拐点数组,把每个拐点的x和y坐标拿到,就以此为圆心,调用context.arc()来画圆(参数为圆心x,y,半径大小,圆弧的起点和终点,是否逆时针绘制),填充白色(为了挡住拐点处的折线),描上橙色的边我再来说一个点,特殊点的位置画出来的圆半径更大、线条更粗,而其他的圆半径和线条正常,这个区别要怎么处理我会在调用arc方法之前,先判断当前是否是特殊点,如果是,则让半径乘以1.8再来画圆,否则不修改半径,直接画圆。

二、只有小圆带有阴影

仅仅画好了每个拐点处的小圆本身,还不够,我看到UI设计图上,每个小圆是有阴影的。现在我们来为小圆画上阴影。

现在又要回答一个问题,canvas要怎么绘制阴影呢?我查阅文档之后给出了我的回答——使用context.setShadow方法,前两个参数表示阴影在x和y方向上的平移,第三个参数表示阴影的模糊半径,第四个参数是阴影的颜色。OK,那么我在调用context.arc画圆之前就调用context.setShadow吧,so easy!效果如下图所示,小圆上有向右向下的半透明红色阴影。

但是,还有一个不容忽视的问题!我在后来绘制价格文字的时候傻眼了,因为文字也带上了阴影!这该怎么办呢?我找遍了文档,也没有找到取消阴影的API,也就是说,context.setShadow调用后,后续画出来的东西都会带有这样的阴影!可我们的需求并不是这样的呀。文字上并没有带有红色的阴影。这该怎么办呢?

某部动画片里有一句话叫“用魔法才能打败魔法”,我觉得可以用在这里——“用阴影才能打败阴影”,换句话说,只有设置成那样的阴影,才能不在后续的绘图中显示这样的阴影。我还是没说明白吗?——如果你把“那样”的阴影设置成“不偏移,不模糊”的阴影,那么阴影是不是就与我们绘制出来的图像完全重合,无法被看见了呢?这就是我去掉阴影的办法。(此处非常感谢我的一位同事,是他想到了这个办法。)

所以,综上所述,我们应该在绘制小圆之前,调用context.setShadow,设置出这样的红色阴影,然后调用context.arc画出小圆,之后再次调用context.setShadow把阴影设为“不偏移,不模糊”,再去绘制其他东西,就可以满足需求了。

最后,来贴一下我绘制拐点的函数的代码:

  /**
     * 绘制拐点处的小圆
     * @param {*} context 上下文对象
     * @param {*} color 使用的颜色
     * @param {*} center 圆心的信息
     * @param {*} r 半径
     * @param {*} isSpecial 是否特殊点
     */
    function drawInflectionPoint(context, color, center, r, isSpecial) {
      context.beginPath();
      // 特殊情况半径更大,线条更粗
      if (isSpecial) {
        r = r * 1.8;
        context.lineWidth = 6 * _this.data.toPx;
      } else {
        context.lineWidth = 4 * _this.data.toPx;
      }
      // 设置阴影,再画圆
      context.setShadow(1, 2, 3, color);
      context.arc(center.x, center.y, r * _this.data.toPx, 0, 2 * Math.PI);
      context.fillStyle = "#ffffff";
      context.fill();
      context.stroke();
      // draw传入true,保留上一次的结果
      context.draw(true);
      context.closePath();
      // 去掉阴影,再画其他的
      context.setShadow(0, 0, 0, color);
    }

非常感谢大家的阅读!下一篇准备写这个图里的价格和拼团人数,重点应该是最低价那里的胶囊图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值