検索
ホームページWeChat アプレットミニプログラム開発WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

WeChat アプレットで天気折れ線グラフを描画するにはどうすればよいですか?次の記事では、キャンバスを使用して WeChat アプレットで天気折れ線グラフを描画し、3 次ベジェ曲線を使用して温度ポイントをフィッティングして滑らかにし、曲線の下部に背景色を付ける方法を紹介します。 . 皆様のお役に立てれば幸いです!

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

ポリライン

レンダリング:

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

##カスタム コンポーネントの折れ線グラフ

<canvas type="2d" id="line" class="line-class"   style="max-width:90%" />
Component({
  externalClasses: [&#39;line-class&#39;],
  properties: {
    width: String,
    height: String,
    data: Array,
  },
  observers: {
    width() {
      // 这里监听 width 变化重绘 canvas
      // 动态传入 width 好像只能这样了..
      const query = this.createSelectorQuery();
      query
        .select(&#39;#line&#39;)
        .fields({ node: true, size: true })
        .exec(res => {
          const canvas = res[0].node;
          const ctx = canvas.getContext(&#39;2d&#39;);
          const width = res[0].width; // 画布宽度
          const height = res[0].height; // 画布高度

          console.log(`宽度: ${width}, 高度: ${height}`);

          const dpr = wx.getSystemInfoSync().pixelRatio;
          canvas.width = width * dpr;
          canvas.height = height * dpr;
          ctx.scale(dpr, dpr);

          // 开始绘图
          this.drawLine(ctx, width, height, this.data.data);
        });
    },
  },
  methods: {
    drawLine(ctx, width, height, data) {
      const Max = Math.max(...data);
      const Min = Math.min(...data);

      // 把 canvas 的宽度, 高度按一定规则平分
      const startX = width / (data.length * 2), // 起始点的横坐标 X
        baseY = height * 0.9, // 基线纵坐标 Y
        diffX = width / data.length,
        diffY = (height * 0.7) / (Max - Min); // 高度预留 0.2 写温度

      ctx.beginPath();
      ctx.textAlign = &#39;center&#39;;
      ctx.font = &#39;13px Microsoft YaHei&#39;;
      ctx.lineWidth = 2;
      ctx.strokeStyle = &#39;#ABDCFF&#39;;

      // 画折线图的线
      data.forEach((item, index) => {
        const x = startX + diffX * index,
          y = baseY - (item - Min) * diffY;

        ctx.fillText(`${item}°`, x, y - 10);
        ctx.lineTo(x, y);
      });
      ctx.stroke();

      // 画折线图背景
      ctx.lineTo(startX + (data.length - 1) * diffX, baseY); // 基线终点
      ctx.lineTo(startX, baseY); // 基线起点
      const lingrad = ctx.createLinearGradient(0, 0, 0, height * 0.7);
      lingrad.addColorStop(0, &#39;rgba(255,255,255,0.9)&#39;);
      lingrad.addColorStop(1, &#39;rgba(171,220,255,0)&#39;);
      ctx.fillStyle = lingrad;
      ctx.fill();

      // 画折线图上的小圆点
      ctx.beginPath();
      data.forEach((item, index) => {
        const x = startX + diffX * index,
          y = baseY - (item - Min) * diffY;

        ctx.moveTo(x, y);
        ctx.arc(x, y, 3, 0, 2 * Math.PI);
      });
      ctx.fillStyle = &#39;#0396FF&#39;;
      ctx.fill();
    },
  },
});

data は [1, 2, ...] などの温度配列です。

温度がいくつあるかわからないためです。値があるため、ここの幅は動的に渡されます。

小さな問題があります。つまり、幅が大きすぎると、実際のマシンでは表示されません...

 // 获取 scroll-view 的总宽度
 wx.createSelectorQuery()
      .select(&#39;.hourly&#39;)
      .boundingClientRect(rect => {
        this.setData({
          scrollWidth: rect.right - rect.left,
        });
      })
      .exec();
<view class="title">小时概述</view>
<scroll-view scroll-x scroll-y class="scroll" show-scrollbar="{{false}}" enhanced="{{true}}">
    <view class="hourly">
      <view wx:for="{{time}}" wx:key="index">{{item}}</view>
    </view>
    <line-chart line-class="line" width="{{scrollWidth}}" height="100" data="{{temp}}" />
</scroll-view>

ここにscroll-xとscroll-yを書きます。そうする必要があります。絶対位置オフセットの問題はありません。理由はわかりません。

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

.scroll {
  position: relative;
  height: 150px;
  width: 100%;
}

.hourly {
  display: flex;
  height: 150px;
  position: absolute;
  top: 0;
}

.hourly > view {
  min-width: 3.5em;
  text-align: center;
}

.line { // 折线图绝对定位到底部
  position: absolute;
  bottom: 0;
}

ここで使用される絶対位置は、実際には、ブロック内の門司天気と毎日のような折れ線グラフをシミュレートするためです。内部の効果なので、毎時はスクロールビューと同じ高さにする必要があり、キャンバスを配置する必要があります

主にMoji Weather がどのように実装されているかわからないので、これは一時的にしかできません

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

3 次ベジェ曲線

レンダリング

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

えっと、あまりスムーズとは思えません

コントロール ポイントの計算

最初にポイント クラスを作成します

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

キャンバス ベジェ曲線描画ツール (karlew.com)

http://wx.karlew.com/canvas/bezier/

3 次ベジェ曲線の各パラメータの意味は、上記の Web サイトで知ることができます。

WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

つまり、bezierCurveTo を使用する場合、最後の点は次の点、最初の 2 つは制御点です。

制御点の計算リファレンス: ベジェ曲線制御点決定方法 - Baidu Library

https://wenku. baidu.com/view/c790f8d46bec0975f565e211.html

#要約すると次のようになります

#a と b には任意の正の数を指定できますWeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

それでは、ある点の制御点 A と B を計算するメソッドを定義します

/**
 * 计算当前点的贝塞尔曲线控制点
 * @param {Point} previousPoint: 前一个点
 * @param {Point} currentPoint: 当前点
 * @param {Point} nextPoint1: 下一个点
 * @param {Point} nextPoint2: 下下个点
 * @param {Number} scale: 系数
 */
calcBezierControlPoints(
  previousPoint,
  currentPoint,
  nextPoint1,
  nextPoint2,
  scale = 0.25
) {
  let x = currentPoint.x + scale * (nextPoint1.x - previousPoint.x);
  let y = currentPoint.y + scale * (nextPoint1.y - previousPoint.y);

  const controlPointA = new Point(x, y); // 控制点 A

  x = nextPoint1.x - scale * (nextPoint2.x - currentPoint.x);
  y = nextPoint1.y - scale * (nextPoint2.y - currentPoint.y);

  const controlPointB = new Point(x, y); // 控制点 B

  return { controlPointA, controlPointB };
}

ここでのスケールは a と b ですが、それらの値は等しいです

ただし、最初の点にはpreviousPointがなく、最後から2番目のポイントにはnextPoint2がない

したがって、ポイントが最初の場合は、previousPointの代わりにcurrentPointを使用します

最後から2番目のポイントの場合は、nextPoint2の代わりにnextPoint1を使用します

最後の点については、bezierCurveTo の 3 番目のパラメータが次のパラメータであるため、何もする必要はありません。座標を指定するだけで点を接続できます。制御点を計算する必要はありません WeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)

したがって、3 次ベジェ曲線を描画する方法:

/**
 * 绘制贝塞尔曲线
 * ctx.bezierCurveTo(控制点1, 控制点2, 当前点);
 */
drawBezierLine(ctx, data, options) {
  const { startX, diffX, baseY, diffY, Min } = options;

  ctx.beginPath();
  // 先移动到第一个点
  ctx.moveTo(startX, baseY - (data[0] - Min) * diffY);

  data.forEach((e, i) => {
    let curPoint, prePoint, nextPoint1, nextPoint2, x, y;

    // 当前点
    x = startX + diffX * i;
    y = baseY - (e - Min) * diffY;
    curPoint = new Point(x, y);

    // 前一个点
    x = startX + diffX * (i - 1);
    y = baseY - (data[i - 1] - Min) * diffY;
    prePoint = new Point(x, y);

    // 下一个点
    x = startX + diffX * (i + 1);
    y = baseY - (data[i + 1] - Min) * diffY;
    nextPoint1 = new Point(x, y);

    // 下下个点
    x = startX + diffX * (i + 2);
    y = baseY - (data[i + 2] - Min) * diffY;
    nextPoint2 = new Point(x, y);

    if (i === 0) {
      // 如果是第一个点, 则前一个点用当前点代替
      prePoint = curPoint;
    } else if (i === data.length - 2) {
      // 如果是倒数第二个点, 则下下个点用下一个点代替
      nextPoint2 = nextPoint1;
    } else if (i === data.length - 1) {
      // 最后一个点直接退出
      return;
    }

    const { controlPointA, controlPointB } = this.calcBezierControlPoints(
      prePoint,
      curPoint,
      nextPoint1,
      nextPoint2
    );

    ctx.bezierCurveTo(
      controlPointA.x,
      controlPointA.y,
      controlPointB.x,
      controlPointB.y,
      nextPoint1.x,
      nextPoint1.y
    );
  });

  ctx.stroke();
},

[関連する学習の推奨事項:

アプレット開発チュートリアル

]

以上がWeChat アプレットでキャンバスを使用して天気折れ線グラフを描画する方法を段階的に説明します (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は掘金社区で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境