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


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 相关文章推荐
javascript对话框使用方法(警告框 javascript确认框 提示框)
Jan 07 Javascript
使用JavaScript实现网页版Pongo设计思路及源代码分享
Jun 16 Javascript
javascript使用window.open提示“已经计划系统关机”的原因
Aug 15 Javascript
js实现文字在按钮上滚动的方法
Aug 20 Javascript
jQuery Easyui学习之datagrid 动态添加、移除editor
Jan 27 Javascript
jquery注册文本框获取焦点清空,失去焦点赋值的简单实例
Sep 08 Javascript
JavaScript正则表达式替换字符串中图片地址(img src)的方法
Jan 13 Javascript
Angular HMR(热模块替换)功能实现方法
Apr 04 Javascript
利用jsonp解决js读取本地json跨域的问题
Dec 11 Javascript
小程序云开发获取不到数据库记录的解决方法
May 18 Javascript
重学JS之显示强制类型转换详解
Jun 30 Javascript
vue excel上传预览和table内容下载到excel文件中
Dec 10 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
fleaphp crud操作之find函数的使用方法
2011/04/23 PHP
php和js如何通过json互相传递数据相关问题探讨
2013/02/26 PHP
jqPlot jquery的页面图表绘制工具
2009/07/25 Javascript
javascript 继承实现方法
2009/08/26 Javascript
5款Javascript颜色选择器
2009/10/25 Javascript
EASYUI TREEGRID异步加载数据实现方法
2012/08/22 Javascript
jQuery中的jQuery()方法用法分析
2014/12/27 Javascript
jQuery ui实现动感的圆角渐变网站导航菜单效果代码
2015/08/26 Javascript
把普通对象转换成json格式的对象的简单实例
2016/07/04 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
AngularJs篇:使用AngularJs打造一个简易权限系统的实现代码
2016/12/26 Javascript
动态加载css方法实现和深入解析
2017/01/18 Javascript
浅谈vue中组件绑定事件时是否加.native
2019/11/09 Javascript
vue中destroyed方法的使用说明
2020/07/21 Javascript
vue 弹出遮罩层样式实例
2020/07/22 Javascript
在vue中实现清除echarts上次保留的数据(亲测有效)
2020/09/09 Javascript
vue radio单选框,获取当前项(每一项)的value值操作
2020/09/10 Javascript
Python 文件操作实现代码
2009/10/07 Python
Python中MySQL数据迁移到MongoDB脚本的方法
2016/04/28 Python
python装饰器初探(推荐)
2016/07/21 Python
浅谈python for循环的巧妙运用(迭代、列表生成式)
2017/09/26 Python
python使用itchat库实现微信机器人(好友聊天、群聊天)
2018/01/04 Python
python实现蒙特卡罗方法教程
2019/01/28 Python
我用Python抓取了7000 多本电子书案例详解
2019/03/25 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
基于Python2、Python3中reload()的不同用法介绍
2019/08/12 Python
python实现淘宝购物系统
2019/10/25 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
2020/07/01 Python
优衣库英国官网:UNIQLO英国
2016/12/25 全球购物
英国家用电器购物网站:Hughes
2018/02/23 全球购物
北京鼎普科技股份有限公司软件测试面试题
2012/04/07 面试题
文化活动实施方案
2014/03/28 职场文书
事业单位考核材料
2014/05/21 职场文书
护校行动方案
2014/05/31 职场文书
小学生九一八纪念日83周年演讲稿500字
2014/09/17 职场文书
村主任“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书