微信小程序获取页面节点方法简介。canvas 滑动验证码 (前段,微信小程序,canvas2D)

目录

一.wx.createSelectorQuery():返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替

二.SelectorQuery.select(string selector)  返回值是NodesRef

三.NodesRef 

四:执行所有请求 NodesRef SelectorQuery.exec

五:canvas 滑动验证码(使用wx.createSelectorQuery()做一个小小的实践)


微信小程序获取页面上的节点信息:微信小程序官方文档

一.wx.createSelectorQuery():返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替

代码:wxml

<!-- 以画布举例 -->
<canvas id="myCanvas" type="2d"></canvas>

代码:js

	/**
	 * 生命周期函数--监听页面加载
	 */
	onLoad: function (options) {
		wx.createSelectorQuery()
	},

二.SelectorQuery.select(string selector)  返回值是NodesRef

(注:SelectorQuery是wx.createSelectorQuery()的返回值  )

方法:

        1.SelectorQuery SelectorQuery.in(Component component):将选择器的选取范围更改为自定义组件 component 内。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)

        2.NodesRef SelectorQuery.select(string selector):(我用到最多的,接下来以此方法为例)在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。

                string selector语法:selector类似于 CSS 的选择器,但仅支持下列语法。(ID选择器,class选择器,子元素选择器,后代选择器,跨自定义组件的后代选择器,多选择器的并集)

        3.NodesRef SelectorQuery.selectAll(string selector):在当前页面下选择匹配选择器 selector 的所有节点

        4.NodesRef SelectorQuery.selectViewport():选择显示区域。可用于获取显示区域的尺寸、滚动位置等信息

        5.NodesRef SelectorQuery.exec(function callback):执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。

代码:js

	onLoad: function (options) {
	    wx.createSelectorQuery().select("#myCanvas")
	},

三.NodesRef 

(注:NodesRef 是SelectorQuery.select的返回值  )

方法: 每个方法的返回值都是SelectorQuery(调用NodesRef SelectorQuery.exec(function callback)执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。)

SelectorQuery NodesRef.fields(Object fields, NodesRef.FieldsCallback callback)

获取节点的相关信息。需要获取的字段在 fields 中指定。返回值是 nodesRef 对应的 selectorQuery

SelectorQuery NodesRef.boundingClientRect(NodesRef.boundingClientRectCallback callback)

添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery

SelectorQuery NodesRef.scrollOffset(NodesRef.scrollOffsetCallback callback)

添加节点的滚动位置查询请求。以像素为单位。节点必须是 scroll-view 或者 viewport,返回 NodesRef 对应的 SelectorQuery

SelectorQuery NodesRef.context(NodesRef.contextCallback callback)

添加节点的 Context 对象查询请求。目前支持 VideoContextCanvasContextLivePlayerContextEditorContext和 MapContext 的获取。

SelectorQuery NodesRef.node(NodesRef.nodeCallback callback)

获取 Node 节点实例。

代码:js 注:这个时候是没有输出的。

	onLoad: function (options) {
		// 获取节点的相关信息
		wx.createSelectorQuery().select("#myCanvas").fields({id:true,size:true,node:true},(res) => {
			console.log(res)//{id: "myCanvas", width: 300, height: 150, nodeCanvasType: "2d", node: gE}  注:但是这个时候是没有输出的
		})

	    //添加节点的布局位置的查询请求
		wx.createSelectorQuery().select("#myCanvas").boundingClientRect((res) => {
			res.id      // 节点的ID
			res.dataset // 节点的dataset
			res.left    // 节点的左边界坐标
			res.right   // 节点的右边界坐标
			res.top     // 节点的上边界坐标
			res.bottom  // 节点的下边界坐标
			res.width   // 节点的宽度
			res.height  // 节点的高度
		})

		// //添加节点的滚动位置查询请求
		wx.createSelectorQuery().select("#myCanvas").scrollOffset()

		// //添加节点的 Context 对象查询请求
		wx.createSelectorQuery().select("#myCanvas").context()

		// //获取 Node 节点实例。
		wx.createSelectorQuery().select("#myCanvas").node()

	}

四:执行所有请求

NodesRef SelectorQuery.exec(function callback)

执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。

代码:js:js 注:是在这个时候输出的

onLoad: function (options) {
		console.log(1)
		// 获取节点的相关信息
		wx.createSelectorQuery().select("#myCanvas").fields({id:true,size:true,node:true},(res) => {
			console.log(res) //{id: "myCanvas", width: 300, height: 150, nodeCanvasType: "2d", node: gE}
		}).exec()

		// //添加节点的布局位置的查询请求
		wx.createSelectorQuery().select("#myCanvas").boundingClientRect((res) => {
			res.id      // 节点的ID
			res.dataset // 节点的dataset
			res.left    // 节点的左边界坐标
			res.right   // 节点的右边界坐标
			res.top     // 节点的上边界坐标
			res.bottom  // 节点的下边界坐标
			res.width   // 节点的宽度
			res.height  // 节点的高度
		}).exec(res => {
			console.log(res)  //[{…}]  展开 0: {id: "myCanvas", dataset: {…}, left: 0, right: 300, top: 0, …}
		})
	},

canvas 滑动验证码(使用wx.createSelectorQuery()做一个小小的实践)

微信小程序canvas画布。2.9.0 起支持一套新 Canvas 2D 接口(需指定 type 属性),同时支持同层渲染

html

<view class="container">
  <view class="code-canvas">
    <canvas id="myCanvas" type="2d"></canvas>
    <canvas id="codeCanvas" type="2d" style="width:{{rectWidth}}rpx;height: {{rectWidth}}rpx;"></canvas>
    <canvas id="activeCanvas" type="2d"  bindtouchstart="onStart" bindtouchmove="onMove" bindtouchend="onEnd"></canvas>
  </view>
</view>

css

.code-canvas{
  position: relative;
  width: 600rpx;
  height: 300rpx;
}
#myCanvas,#activeCanvas{
  position: absolute;
  width: 600rpx;
  height: 300rpx;

}
#codeCanvas{
  position: absolute;
}

js

// pages/index/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    // 正方形宽
    rectWidth: 80,
    // 圆的半径
    r:10,
    // x坐标
    x: null,
    // y坐标
    y: 100,
    left:0,
    randX:0,
    // 开始触摸 并且触摸在验证码范围上
    isStart:false,
  },
  onLoad() {
    // 获取画布实例
    wx.createSelectorQuery().select("#myCanvas").fields({
      node: true,
      size: true
    }).exec(res => {
      const myCanvas = res[0].node;
      // 获取比例
      const ratio = wx.getSystemInfoSync().screenWidth / 750;
      this.data.ratio = ratio
      myCanvas.width = res[0].width / ratio;
      myCanvas.height = res[0].height / ratio;

      // 获取canvas 2d绘图上下文
      const ctx = myCanvas.getContext("2d");
      // 创建图片对象
      let bgImage = myCanvas.createImage();
      bgImage.src = "3.jpg";
      bgImage.onload = () => {
        // 画出背景
        ctx.drawImage(bgImage, 0, 0, myCanvas.width, myCanvas.height);

        // 随机x的值
        let randX = this.minRand(myCanvas.width / 2, myCanvas.width - this.data.rectWidth);
        this.data.randX = randX;
        // 获取遮盖块下的图画
        let codeImage1 = ctx.getImageData(randX, this.data.y, this.data.rectWidth, this.data.rectWidth);
        // 遮盖快
        this.playCode(ctx, true, randX, this.data.y);

        // 导出图片背景
        let bgImageUrl = myCanvas.toDataURL("image/png");
        this.setData({
          bgImageUrl: bgImageUrl
        });

        // 二
        wx.createSelectorQuery().select("#codeCanvas").fields({
          node: true,
          size: true
        }).exec(res => {
          const codeCanvas = res[0].node;
          codeCanvas.width = res[0].width / ratio;
          codeCanvas.height = res[0].height / ratio;

          // 获取canvas 2d绘图上下文
          const codeCtx = codeCanvas.getContext("2d");
          codeCtx.putImageData(codeImage1, 0, 0);
          let codeImage = codeCanvas.toDataURL("image/png");
          this.setData({
            codeImage: codeImage
          });

          // 清除画布二的内容
          codeCtx.clearRect(0, 0, codeCanvas.width, codeCanvas.height);

          // 创建图片对象
          let codeImagePlay = codeCanvas.createImage();
          codeImagePlay.src = codeImage;
          codeImagePlay.onload = () => {
            this.playCode(codeCtx, false, 0, 0)
            codeCtx.drawImage(codeImagePlay, 0, 0, codeCanvas.width, codeCanvas.height)
            let getCodeImagePlay = codeCtx.getImageData(0, 0, codeCanvas.width, codeCanvas.height)
            codeImage = codeCanvas.toDataURL("image/png");
            this.setData({
              codeImage: codeImage
            });
            codeCtx.clearRect(0,0,codeCanvas.width,codeCanvas.height);

            // 三
            wx.createSelectorQuery().select("#activeCanvas").fields({
              node: true,
              size: true
            }).exec(res => {
              let that = this
              const activeCanvas = res[0].node;
              activeCanvas.width = res[0].width / ratio;
              activeCanvas.height = res[0].height / ratio;

              // 获取canvas 2d绘图上下文
              const ctx3 = activeCanvas.getContext("2d");
              let xx = 0;
              let animation = function(){
                  xx = that.data.left;
                ctx3.clearRect(0,0,activeCanvas.width,activeCanvas.height);
                ctx3.putImageData(getCodeImagePlay, xx, that.data.y)
                activeCanvas.requestAnimationFrame(animation)
              }
              activeCanvas.requestAnimationFrame(animation)
            })
          }
        })
      }
    })
    console.log("data", this.data)
  },

  // 触摸开始,记录触摸时的位置,并且确定触摸在验证码范围内
  onStart(e){
    console.log("开始")
    this.data.isOnNum = true;
    let startX = e.touches[0].x / this.data.ratio;
    let startY = e.touches[0].y / this.data.ratio;
    let x = this.data.left
    console.log(x,startX)
    if((startX >= x && startX <= x + this.data.rectWidth) && (startY >= this.data.y && startY <= this.data.y + this.data.rectWidth)){
    console.log("开始1")
      this.setData({
        startX:startX,
        isStart:true
      })
    }
  },

  // 手指触摸移动,移动范围不在验证码背景中验证码回到初始位置
  onMove(e){
    if(this.data.isStart){
    console.log("移动")

      let startX = this.data.startX;
      let activeX = e.touches[0].x;
      let left = ((activeX - startX) + startX) / this.data.ratio;
      left = left + 0
      if(left <= 0 || left >= 600){
        left = 0
      }
      this.setData({
        left:left
      })
    }
  },

  // 触摸结束。验证码图案与背景图相差不过5。验证成功
  onEnd(e){
    if(this.data.isStart){
      if(this.data.randX - this.data.left <= 5 && this.data.randX - this.data.left >= -5){
        this.data.left = this.data.left
      }else{
        this.data.left = 0
      }
      this.data.isStart = false
    }
    
  },

  /**
   * 多边形  以宽80的图形为例
   * @param {*} canvas  canvas 2d绘图上下文
   * @param {*} bool 布尔值多边形如何展示
   * @param {*} x x坐标
   * @param {*} y y坐标
   */
  playCode(canvas, bool, x, y) {
    let width = this.data.rectWidth
    let r = this.data.r
    canvas.beginPath()
    if (bool) {
      canvas.fillStyle = "#999"
    } else {
      canvas.strokeStyle = "#00000000"
    }
    canvas.moveTo(x, y + r)
    canvas.lineTo(x + (width/2 - r), y + r)
    canvas.arcTo(x + (width/2 - r), y, x + (width/2), y, r)
    canvas.arcTo(x + (width/2 + r), y, x + (width/2 + r), y + r, r)
    canvas.lineTo(x + width, y + r)
    canvas.lineTo(x + width, y + width)
    canvas.lineTo(x + (width/2 + r), y + width)
    canvas.arcTo(x + (width/2 + r), y + (width - r), x + (width/2), y + (width - r), r)
    canvas.arcTo(x + (width/2 - r), y + (width - r), x + (width/2 - r), y + width, r)
    canvas.lineTo(x, y + width)
    canvas.lineTo(x, y + (width/2 + r))
    canvas.arcTo(x + r, y + (width/2 + r), x + r, y + (width/2), r)
    canvas.arcTo(x + r, y + (width/2 - r), x, y + (width/2 - r), r)
    canvas.lineTo(x, y + (width/2 - r))
    canvas.closePath()
    if (bool) {
      canvas.fill()
    } else {
      canvas.clip()
      canvas.stroke()
    }
  },

  // 随机数 最小值
  minRand(min, max) {
    return Math.floor(Math.random() * (max - min) + min)
  }

})

注:1.用来以后回忆现在的代码水平

        2.代码有问题望指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值