微信小程序实现带刻度尺滑块功能


Posted in Javascript onMarch 29, 2017

摘要: 与自带的slider不同的是,它是通过手势滑动标尺得到取值,而不是通过滑动滑块本身。

效果图

微信小程序实现带刻度尺滑块功能

场景

当一屏显示不下,例如年龄体重选择,金额选择等大区间需要的选择器,相比自带的picker要直观一些。

思路:

先画一个scrollView 2 装进canvas

lineTo画刻度线段,lineTo+fill画出三角形游标,fillText描绘文本标签

通过bindscroll监听刻度尺触摸事件

渲染取值到页面

基本布局

<scroll-view scroll-x="true" bindscroll="bindscroll">
  <canvas canvas-id="canvas" id="canvas"></canvas>
</scroll-view>

实现bindscroll方法

bindscroll: function (e) {
  // deltaX 水平位置偏移位,每次滑动一次触发一次,所以需要记录从第一次触发滑动起,一共滑动了多少距离
  deltaX += e.detail.deltaX;
  console.log(deltaX)
}

描绘刻度

const context = wx.createCanvasContext('canvas-ruler');
// 移动到原点
context.moveTo(origion.x, origion.y);
// 画线到刻度高度
context.lineTo(origion.x, origion.y - heightDecimal);
// 设置属性
context.setLineWidth(1);
// 描线
context.stroke();
// 描绘文本标签
context.setFontSize(fontSize);
context.fillText('0', origion.x - fontSize / 2, fontSize);
context.draw();

遍历刻度

for (var i = 0; i <= maxValue; i++) {
  // 开始一个路径,这条非常重要,否则会重复绘制之前的刻度n次,效果表现为页面加载很卡,lineWidth得到的线很粗
  context.beginPath();
  // 绘制同上,不再赘述
  ...
  // 关闭一个路径,它是可选的,调用过了beginPath,不关闭也没有影响,保险起见,加上它
  context.closePath();
}

切记要调用context.beginPath();

描绘游标

drawCursor: function () {
    /* 定义变量 */
    // 定义三角形顶点 TODO x
    var center = {x: app.screenWidth / 2, y: 5};
    // 定义三角形边长
    var length = 20;
    // 左端点
    var left = {x: center.x - length / 2, y: center.y + length / 2 * Math.sqrt(3)};
    // 右端点
    var right = {x: center.x + length / 2, y: center.y + length / 2 * Math.sqrt(3)};
    // 初始化context
    const context = wx.createCanvasContext('canvas-cursor');
    context.moveTo(center.x, center.y);
    context.lineTo(left.x, left.y);
    context.lineTo(right.x, right.y);
    // fill()填充而不是stroke()描边,于是省去手动回归原点,context.lineTo(center.x, center.y);
    context.setFillStyle('#48c23d');
    context.fill();
    context.draw();
  }

画带一个绿色的正三角形作为游标,注意游标是悬浮不动的,所以另起一个cancas来装它。当然它不是必须的,偷个懒ps一张三角形的png代替也无妨,甚至刻度其实也可以用<view style="background: gray; width: 2px;">加绝对定位来生成的。

定义刻度默认初值

that.setData({
    scrollLeft: (currentValue - minValue) * ratio
});
<scroll-view scroll-x="true" bindscroll="bindscroll" scroll-left="{{scrollLeft}}">

绑定scroll-left参数,相当于iOS里了UIScrollView的contentOffset,手动让偏移到默认初值对应的坐标位置。

适配最小值

当业务场景需要做数据验证,例如金额要>0,年龄要大于18岁等,就得适配极值。

that.setData({
    amount: Math.floor(- deltaX / 10 + minValue)
});

同时要修正刻度线的x轴坐标

// 2.2 画刻度线
context.moveTo(origion.x + (i - minValue) * ratio, origion.y);
// 画线到刻度高度,10的位数就加高
context.lineTo(origion.x + (i - minValue) * ratio, origion.y - (i % ratio == 0 ? heightDecimal : heightDigit));
// 2.3 描绘文本标签
context.fillText(i == 0 ? ' ' + i : i, origion.x + (i - minValue) * ratio - fontSize / 2, fontSize);

最终js代码

var that;
var deltaX = 0;
var minValue = 1;
var app = getApp();
Page({
  data: {
    value: 0,
    canvasHeight: 80
  },
  onLoad: function (options) {
    that = this;
    // 绘制标尺
    that.drawRuler();
    // 绘制三角形游标
    that.drawCursor();
  },
  drawRuler: function() {
    /* 1.定义变量 */
    // 1.1 定义原点与终点,x轴方向起点与终点各留半屏空白
    var origion = {x: app.screenWidth / 2, y: that.data.canvasHeight};
    var end = {x: app.screenWidth / 2, y: that.data.canvasHeight};
    // 1.2 定义刻度线高度
    var heightDecimal = 50;
    var heightDigit = 25;
    // 1.3 定义文本标签字体大小
    var fontSize = 20;
    // 1.4 最小刻度值
    // 已经定义在全局,便于bindscroll访问
    // 1.5 总刻度值
    var maxValue = 200;
    // 1.6 当前刻度值
    var currentValue = 20;
    // 1.7 每个刻度所占位的px
    var ratio = 10;
    // 1.8 画布宽度
    var canvasWidth = maxValue * ratio + app.screenWidth - minValue * ratio;
    // 设定scroll-view初始偏移
    that.setData({
      canvasWidth: canvasWidth,
      scrollLeft: (currentValue - minValue) * ratio
    });
    /* 2.绘制 */
    // 2.1初始化context
    const context = wx.createCanvasContext('canvas-ruler');
    // 遍历maxValue
    for (var i = 0; i <= maxValue; i++) {
      context.beginPath();
      // 2.2 画刻度线
      context.moveTo(origion.x + (i - minValue) * ratio, origion.y);
      // 画线到刻度高度,10的位数就加高
      context.lineTo(origion.x + (i - minValue) * ratio, origion.y - (i % ratio == 0 ? heightDecimal : heightDigit));
      // 设置属性
      context.setLineWidth(2);
      // 10的位数就加深
      context.setStrokeStyle(i % ratio == 0 ? 'gray' : 'darkgray');
      // 描线
      context.stroke();
      // 2.3 描绘文本标签
      context.setFillStyle('gray');
      if (i % ratio == 0) {
        context.setFontSize(fontSize);
        // 为零补一个空格,让它看起来2位数,页面更整齐
        context.fillText(i == 0 ? ' ' + i : i, origion.x + (i - minValue) * ratio - fontSize / 2, fontSize);
      }
      context.closePath();
    }
    // 2.4 绘制到context
    context.draw();
  },
  drawCursor: function () {
    /* 定义变量 */
    // 定义三角形顶点 TODO x
    var center = {x: app.screenWidth / 2, y: 5};
    // 定义三角形边长
    var length = 20;
    // 左端点
    var left = {x: center.x - length / 2, y: center.y + length / 2 * Math.sqrt(3)};
    // 右端点
    var right = {x: center.x + length / 2, y: center.y + length / 2 * Math.sqrt(3)};
    // 初始化context
    const context = wx.createCanvasContext('canvas-cursor');
    context.moveTo(center.x, center.y);
    context.lineTo(left.x, left.y);
    context.lineTo(right.x, right.y);
    // fill()填充而不是stroke()描边,于是省去手动回归原点,context.lineTo(center.x, center.y);
    context.setFillStyle('#48c23d');
    context.fill();
    context.draw();
  },
  bindscroll: function (e) {
    // deltaX 水平位置偏移位,每次滑动一次触发一次,所以需要记录从第一次触发滑动起,一共滑动了多少距离
    deltaX += e.detail.deltaX;
    // 数据绑定
    that.setData({
      value: Math.floor(- deltaX / 10 + minValue)
    });
    console.log(deltaX)
  }
});

以上所述是小编给大家介绍的微信小程序实现带刻度尺滑块功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 Javascript
JS获取计算机mac地址以及IP的实现方法
Jan 08 Javascript
js中document.write使用过程中的一点疑问解答
Mar 20 Javascript
jQuery插件开发汇总
May 15 Javascript
JavaScript DOM节点操作实例小结(新建,删除HTML元素)
Jan 19 Javascript
axios进阶实践之利用最优雅的方式写ajax请求
Dec 20 Javascript
浅谈Vue2.0父子组件间事件派发机制
Jan 08 Javascript
浅谈Node.js 子进程与应用场景
Jan 24 Javascript
js中call()和apply()改变指针问题的讲解
Jan 17 Javascript
vue点击当前路由高亮小案例
Sep 26 Javascript
vue点击自增和求和的实例代码
Nov 06 Javascript
vue 重塑数组之修改数组指定index的值操作
Aug 09 Javascript
Javascript 详解封装from表单数据为json串进行ajax提交
Mar 29 #Javascript
详解如何在Vue2中实现组件props双向绑定
Mar 29 #Javascript
整理关于Bootstrap警示框的慕课笔记
Mar 29 #Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
Mar 29 #Javascript
jQuery实现字体颜色渐变效果的方法
Mar 29 #jQuery
整理关于Bootstrap导航的慕课笔记
Mar 29 #Javascript
javascript 中Cookie读、写与删除操作
Mar 29 #Javascript
You might like
PHP的Laravel框架中使用AdminLTE模板来编写网站后台界面
2016/03/21 PHP
浅谈PHP值mysql操作类
2016/06/29 PHP
php基于openssl的rsa加密解密示例
2016/07/11 PHP
laravel 操作数据库常用函数的返回值方法
2019/10/11 PHP
跨浏览器开发经验总结(四) 怎么写入剪贴板
2010/05/13 Javascript
javascript针对DOM的应用分析(三)
2012/04/15 Javascript
JQuery中层次选择器用法实例详解
2015/05/18 Javascript
Bootstrap表格和栅格分页实例详解
2016/05/20 Javascript
Bootstrap中的Dropdown下拉菜单更改为悬停(hover)触发
2016/08/31 Javascript
jackson解析json字符串,首字母大写会自动转为小写的方法
2017/12/22 Javascript
JS实现页面鼠标点击出现图片特效
2020/08/19 Javascript
[56:20]LGD vs VP Supermajor 败者组决赛 BO3 第三场 6.10
2018/07/04 DOTA
Python字符和字符值(ASCII或Unicode码值)转换方法
2015/05/21 Python
Python实现的朴素贝叶斯分类器示例
2018/01/06 Python
对python中数组的del,remove,pop区别详解
2018/11/07 Python
python对视频画框标记后保存的方法
2018/12/07 Python
python实现flappy bird小游戏
2018/12/24 Python
python 读取Linux服务器上的文件方法
2018/12/27 Python
python Tkinter版学生管理系统
2019/02/20 Python
使用python实现抓取腾讯视频所有电影的爬虫
2019/04/15 Python
Pandas 重塑(stack)和轴向旋转(pivot)的实现
2019/07/22 Python
Python使用scrapy爬取阳光热线问政平台过程解析
2019/08/14 Python
Python3和pyqt5实现控件数据动态显示方式
2019/12/13 Python
Python谱减法语音降噪实例
2019/12/18 Python
Pandas实现DataFrame按行求百分数(比例数)
2019/12/27 Python
代码总结Python2 和 Python3 字符串的区别
2020/01/28 Python
Django创建一个后台的基本步骤记录
2020/10/02 Python
css实例教程 一款纯css3实现的超炫动画背画特效
2014/11/05 HTML / CSS
奥地利网上现代灯具和灯饰店:Lampenwelt.at
2018/01/29 全球购物
说出一些常用的类,包,接口
2014/09/22 面试题
学生会宣传部部长竞选演讲稿
2014/04/25 职场文书
水污染治理工程专业求职信
2014/06/14 职场文书
农业项目投资意向书
2015/05/09 职场文书
病假证明模板
2015/06/19 职场文书
2016年精神文明建设先进个人事迹材料
2016/02/29 职场文书
python的列表生成式,生成器和generator对象你了解吗
2022/03/16 Python