Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

青灯夜游
Lepaskan: 2022-03-08 20:02:55
ke hadapan
8052 orang telah melayarinya

Bagaimana untuk melukis carta garis cuaca dalam applet WeChat? Artikel berikut akan memperkenalkan kepada anda cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat, dan menggunakan lengkung Bezier tertib ketiga agar sesuai dengan titik suhu untuk menjadikannya licin dan mempunyai warna latar belakang di bahagian bawah lengkung Saya harap Bermanfaat untuk semua orang!

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

Polyline

Rendering:

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

Carta garis komponen tersuai

<canvas type="2d" id="line" class="line-class" style="width:{{width}}px;height:{{height}}px" />
Salin selepas log masuk
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();
    },
  },
});
Salin selepas log masuk

data ialah tatasusunan suhu, seperti [1, 2, ...]

Kerana saya tidak 'Tidak tahu Berapa banyak nilai suhu yang ada, jadi lebar di sini dihantar secara dinamik

Ada masalah kecil, iaitu, jika lebar terlalu besar, mesin sebenar tidak akan memaparkannya. ..

 // 获取 scroll-view 的总宽度
 wx.createSelectorQuery()
      .select(&#39;.hourly&#39;)
      .boundingClientRect(rect => {
        this.setData({
          scrollWidth: rect.right - rect.left,
        });
      })
      .exec();
Salin selepas log masuk
<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>
Salin selepas log masuk

Di sini Tulis tatal-x dan tatal-y, tidak akan ada masalah mengimbangi kedudukan mutlak, dan saya tidak tahu mengapa

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

.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;
}
Salin selepas log masuk

Kedudukan mutlak yang digunakan di sini sebenarnya adalah untuk mensimulasikan Kesan carta garisan seperti Cuaca Moji dan setiap hari dalam blok, jadi ketinggian setiap jam hendaklah sama dengan paparan skrol, dan kanvas perlu diletakkan

Terutamanya kerana saya tidak tahu cara melaksanakan Cuaca Moji, jadi saya hanya boleh melakukan ini buat sementara waktu

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

Ketiga -order Bezier Curve

Rendering

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

emmm, nampak tak lancar sangat

Kira titik kawalan

Mula-mula tulis kelas mata

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}
Salin selepas log masuk

Alat lukisan lengkung Kanvas Bezier (karlew.com)

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

Anda boleh mengetahui susunan ketiga melalui laman web di atas Maksud setiap parameter keluk Bezier

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

Iaitu, apabila menggunakan bezierCurveTo, titik terakhir ialah titik seterusnya, dan dua yang pertama ialah titik kawalan

Rujukan pengiraan titik kawalan: Kaedah menentukan titik kawalan lengkung Bezier - Perpustakaan Baidu

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

Untuk meringkaskannya, ia adalah

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

di mana a dan b boleh menjadi sebarang nombor positif

Jadi tentukan kaedah untuk mengira titik kawalan A dan B bagi titik tertentu

/**
 * 计算当前点的贝塞尔曲线控制点
 * @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 };
}
Salin selepas log masuk

Di sini skala ialah a dan b, tetapi nilainya adalah sama

Tetapi titik pertama tidak mempunyai Titik sebelumnya, dan titik kedua terakhir tidak mempunyai NextPoint2

Jadi apabila titik itu adalah yang pertama, gunakan CurrentPoint dan bukannya previousPoint

Apabila ia adalah titik kedua terakhir, gunakan nextPoint1 dan bukannya nextPoint2

Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod)

Bagi titik terakhir, anda tidak perlu melakukan apa-apa, kerana parameter ketiga bezierCurveTo ialah titik seterusnya Anda hanya perlu menyediakan koordinat untuk menyambung, dan tidak perlu mengira titik kawalan

Oleh itu, kaedah melukis lengkung Bezier tertib ketiga:

/**
 * 绘制贝塞尔曲线
 * 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();
},
Salin selepas log masuk

[Cadangan pembelajaran berkaitan: Tutorial Pembangunan Program Mini]

Atas ialah kandungan terperinci Ajar anda langkah demi langkah cara menggunakan kanvas untuk melukis carta garis cuaca dalam applet WeChat (dengan kod). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan