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


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 相关文章推荐
juqery 学习之四 筛选查找
Nov 30 Javascript
基于jquery的固定表头和列头的代码
May 03 Javascript
js实现格式化金额,字符,时间的方法
Feb 26 Javascript
基于javascript实现彩票随机数生成(升级版)
Apr 17 Javascript
深入理解jquery自定义动画animate()
May 24 Javascript
全面了解javascript中的错误处理机制
Jul 18 Javascript
JavaScript中清空数组的方法总结
Dec 02 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
Mar 02 Javascript
mac上node.js环境的安装测试
Jul 03 Javascript
基于vue2实现左滑删除功能
Nov 28 Javascript
微信小程序实现列表下拉刷新上拉加载
Jul 29 Javascript
vue 内联样式style中的background用法说明
Aug 05 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 zend 相对路径问题
2009/01/12 PHP
php.ini中date.timezone设置分析
2011/07/29 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
PHP页面间参数传递的四种方法详解
2013/06/09 PHP
PHP实现合并discuz用户
2015/08/05 PHP
php 问卷调查结果统计
2015/10/08 PHP
PHP函数checkdnsrr用法详解(Windows平台用法)
2016/03/21 PHP
php设计模式之适配器模式原理、用法及注意事项详解
2019/09/24 PHP
jquery中的$(document).ready()与window.onload的区别
2009/11/18 Javascript
IE和firefox浏览器的event事件兼容性汇总
2009/12/06 Javascript
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
web网页按比例显示图片实现原理及js代码
2013/08/09 Javascript
setInterval计时器不准的问题解决方法
2014/05/08 Javascript
Jquery异步提交表单代码分享
2015/03/26 Javascript
jQuery实现动画效果circle实例
2015/08/06 Javascript
Node.js中路径处理模块path详解
2016/11/14 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
2016/12/30 Javascript
VS Code转换大小写、修改选中文字或代码颜色的方法
2017/12/15 Javascript
JavaScript异步加载问题总结
2018/02/17 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
Angular请求防抖处理第一次请求失效问题
2019/05/17 Javascript
9个JavaScript日常开发小技巧
2020/10/06 Javascript
python中函数默认值使用注意点详解
2016/06/01 Python
Python基于动态规划算法解决01背包问题实例
2017/12/06 Python
Python算法中的时间复杂度问题
2019/11/19 Python
哥伦比亚最大的网上商店:Linio哥伦比亚
2016/09/25 全球购物
ROSEFIELD手表荷兰官方网上商店:北欧极简设计女士腕表品牌
2018/01/24 全球购物
戴尔英国翻新电脑和电子产品:Dell UK Refurbished Computers
2019/07/30 全球购物
模具专业毕业推荐信
2014/03/08 职场文书
商场主管竞聘书
2014/03/31 职场文书
2014教育局对照检查材料思想汇报
2014/09/23 职场文书
2015年新农村建设工作总结
2015/05/22 职场文书
建国大业观后感
2015/06/01 职场文书
阳光体育运动标语口号
2015/12/26 职场文书
Nginx工作原理和优化总结。
2021/04/02 Servers
Redis 彻底禁用RDB持久化操作
2021/07/09 Redis