原生js + canvas 实现刻度尺效果

2023-11-10

欢迎访问我的 个人博客

手势事件
touchstart 手指按下 、touchmove 手指移动 、 touchend 手指抬起

效果图:

在这里插入图片描述

完整代码:

ruler.js

var ruler = {
    /**
     * 初始化刻度尺插件
     * @el 容器 String
     * @height 刻度尺高度 Number
     * @maxScale 最大刻度 Number
     * @startValue 开始的值 Number
     * @region 区间 Array
     * @background 刻度尺背景颜色 String
     * @color 刻度线和字体的颜色 String
     * @markColor  中心刻度标记颜色 String
     * @isConstant 是否不断地获取值 Boolean
     * @success(res) 滑动结束后的回调 Function
     * */
    initPlugin: function (params) {
        var initParams = {
            el: params.el,
            height: params.height || 60,
            maxScale: params.maxScale || 200,
            startValue: params.startValue || 0,
            region: params.region || false,
            background: params.background || false,
            color: params.color || false,
            markColor: params.markColor || "#FFCC33",
            isConstant: params.isConstant || false
        };

        if (!initParams.el) {
            console.warn("没有容器元素的参数");
            return false;
        }

        var rulerWrap = document.getElementById(initParams.el); //获取容器
        rulerWrap.style.height = initParams.height < 50 ? 50 + "px" : initParams.height + "px";

        //最大刻度的小值是50
        initParams.maxScale = initParams.maxScale < 50 ? 50 : initParams.maxScale;

        if (initParams.startValue > initParams.maxScale) {
            initParams.startValue = initParams.maxScale;
        }

        var minSildeNum = 0;//最小滑动的值
        var maxSildeNum = initParams.maxScale;//最大滑动的值

        if (initParams.region) {
            minSildeNum = Math.floor(initParams.region[0]);
            maxSildeNum = Math.floor(initParams.region[1]);
        }

        var count = initParams.startValue; //初始值

        var winWidth = rulerWrap.offsetWidth; //容器宽度
        var division = winWidth / 50; //每个刻度的距离 分割线
        //刻度值数组
        var scaleValueList = [];
        for (var i = 0; i <= initParams.maxScale; i += 10) {
            scaleValueList.push(i);
        }

        var canvas = rulerWrap.getElementsByTagName("canvas")[0]; //获取容器下的canvas标签
        //没有canvas就创建一个
        if (!canvas) {
            canvas = document.createElement("canvas"); //创建canvas标签
            canvas.width = winWidth;
            canvas.height = initParams.height;
            rulerWrap.appendChild(canvas);
        }
        var cxt = canvas.getContext("2d");

        if (window.devicePixelRatio) {
            canvas.width = window.devicePixelRatio * winWidth;
            canvas.height = window.devicePixelRatio * initParams.height;
            cxt.scale(window.devicePixelRatio, window.devicePixelRatio);
        }

        //画刻度尺
        function drawRuler(count) {
            count = count - 25;

            //清空画布
            cxt.clearRect(0, 0, winWidth, initParams.height);

            //刻度尺背景
            if (initParams.background) {
                cxt.fillStyle = initParams.background;
                cxt.fillRect(0, 0, canvas.width, initParams.height);
            }

            //画刻度线
            for (var i = 0; i < initParams.maxScale; i++) {
                cxt.beginPath();
                cxt.save();
                cxt.strokeStyle = initParams.color ? initParams.color : "#bbb";
                cxt.lineWidth = 1;
                cxt.lineCap = "round";
                cxt.moveTo(division * i - count * division, 0);
                cxt.lineTo(division * i - count * division, Math.floor(initParams.height * 0.3));

                if (i % 2 === 0) {
                    cxt.strokeStyle = initParams.color ? initParams.color : "#999";
                    cxt.lineTo(division * i - count * division, Math.floor(initParams.height * 0.35));
                }
                if (i % 10 === 0) {
                    cxt.strokeStyle = initParams.color ? initParams.color : "#666";
                    cxt.lineTo(division * i - count * division, Math.floor(initParams.height * 0.52));
                }

                cxt.stroke();
                cxt.restore();
                cxt.closePath();
            }

            //添加体重数字
            cxt.beginPath();
            cxt.font = "14px Arial";
            cxt.fillStyle = initParams.color ? initParams.color : "#333";
            cxt.textAlign = "center";
            cxt.textBaseline = "middle";
            scaleValueList.forEach(function (num, i) {
                cxt.fillText(num.toString(), (division * i * 10) - (count * division), Math.floor(initParams.height * 0.78));
            });
            cxt.closePath();

            //中心刻度线
            cxt.beginPath();
            cxt.save();
            cxt.strokeStyle = initParams.markColor;
            cxt.lineWidth = 2;
            cxt.lineCap = "round";
            cxt.moveTo((winWidth / 2), 0);
            cxt.lineTo((winWidth / 2), Math.floor(initParams.height * 0.52));
            cxt.stroke();
            cxt.restore();
            cxt.closePath();

        }

        if (window.devicePixelRatio) {
            canvas.style.transform = "scale(" + 1 / window.devicePixelRatio + ")";
            canvas.style.transformOrigin = "left top";
        }

        drawRuler(count);

        //滑动相关
        var initX = 0, //初始x 距离
            endX = 0, //结束x 距离
            distanceX = 0, //移动距离
            _distanceX = 0,// 判断用的移动距离
            lastX = count; //上次移动距离

        if (!canvas) return false;

        //手指按下
        canvas.addEventListener("touchstart", function (e) {
            initX = e.targetTouches[0].pageX;

        }, false);

        //手指滑动
        canvas.addEventListener("touchmove", function (e) {
            endX = e.targetTouches[0].pageX;
            moveEvent();
        }, false);

        //手指抬起
        canvas.addEventListener("touchend", function (e) {
            lastX = count;
            overEvent();
        }, false);

        var isMouseDown = false; //鼠标是否按下

        //鼠标按下
        canvas.addEventListener("mousedown", function (e) {
            isMouseDown = true;
            initX = e.layerX;
        }, false);

        //鼠标移动
        canvas.addEventListener("mousemove", function (e) {
            if (!isMouseDown) {
                return false;
            }
            endX = e.layerX;
            moveEvent();
        }, false);


        //鼠标抬起&离开
        canvas.addEventListener("mouseup", function (e) {
            lastX = count;
            isMouseDown = false;
            overEvent();
        }, false);

        canvas.addEventListener("mouseleave", function (e) {
            if (isMouseDown) {
                lastX = count;
                isMouseDown = false;
                overEvent();
            }
        }, false);


        //手指&鼠标移动事件
        function moveEvent() {
            distanceX = Math.floor((endX - initX) / (winWidth / 50));
            if (distanceX === _distanceX) {
                return false;
            }
            _distanceX = distanceX;
            count = lastX + distanceX;

            if (count >= initParams.maxScale || count <= 0) {
                count = count >= initParams.maxScale ? initParams.maxScale : 0;
            }
            drawRuler(count);

            if (initParams.isConstant) {
                params.success && params.success(count);
            }
        }

        //手指&鼠标结束事件
        function overEvent() {
            if (count > maxSildeNum) {
                lastX = count = count > maxSildeNum ? maxSildeNum : count;
            } else if (count < minSildeNum) {
                lastX = count = count < minSildeNum ? minSildeNum : count;
            } else {

            }
            drawRuler(count);

            //返回最后的值
            params.success && params.success(count);
        }

    }
};

ruler.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>刻度尺</title>
    <meta name="renderer" content="webkit">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .ruler-wrap {
            width: 100%;
            max-width: 600px;
            /*height: 60px;*/
            line-height: 1px;
            overflow: hidden;
            margin: 0 auto 50px;
        }

        .text-input{
            display: block;
            width: 100px;
            height: 30px;
            border-radius: 5px;
            background: #f6f6f6;
            border: none;
            text-align: center;
            font-size: 14px;
            color: #4142cc;
            font-weight: bold;
            letter-spacing: 1px;
            margin: 0 auto;
        }
        .text-input:focus{
            outline: none;
        }
    </style>
</head>
<body>

<!-- 刻度尺容器(必要的) -->
<div class="ruler-wrap" id="ruler"></div>

<!-- 刻度尺容器(必要的) -->
<div class="ruler-wrap" style="width: 90%;" id="ruler2"></div>


<input id="rulerText3" class="text-input" type="text" readonly value="">

<!-- 刻度尺容器(必要的) -->
<div class="ruler-wrap" style="width: 80%;" id="ruler3"></div>


<!-- 引入刻度尺插件js -->
<script src="js/ruler.js"></script>
<script>

    //调用刻度尺方法
    ruler.initPlugin({
        el: "ruler", //容器id
        startValue: 100,
        background: "#f5f5f5",
        success: function (res) {
            console.log(res);
        }
    });

    //调用刻度尺方法
    ruler.initPlugin({
        el: "ruler2", //容器id
        maxScale: 300, //最大刻度
        startValue: 50, //刻度开始的初始值
        region: [10, 200], //选择刻度的区间范围
        background: "#2bd4bc", //刻度尺背景色
        markColor: "#c968ff", //中心刻度标记颜色
        success: function (res) {
            console.log(res);
        }
    });


    var rulerText3 = document.getElementById("rulerText3");
    rulerText3.value = 200;
    //调用刻度尺方法
    ruler.initPlugin({
        el: "ruler3", //容器id
        height: 50, //刻度尺高度
        maxScale: 300, //最大刻度
        startValue: 200, //刻度开始的初始值
        region: [50, 220], //选择刻度的区间范围
        background: "#ffa43c", //刻度尺背景色
        color: "#fff", //刻度线和字体的颜色
        markColor: "#3786db", //中心刻度标记颜色
        isConstant: true, //是否不断地获取值
        success: function (res) {
            console.log(res);
            rulerText3.value = res;
        }
    });

</script>

</body>
</html>

属性说明

属性名 类型 是否必须 默认值 说明
el String 用于包裹canvas的容器
height Number 60 canvas刻度尺的高度,最小值是50
maxScale Number 200 最大刻度值,最小值是50
startValue Number 0 开始时的刻度值
region Array false 选择刻度的区间范围
background String false canvas刻度尺的颜色
color String false 刻度线和字体的颜色
markColor String “#FFCC33” 中心刻度标记颜色
isConstant Boolean false 是否不断地获取值
success Function 返回此刻的值
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

原生js + canvas 实现刻度尺效果 的相关文章

  • Android:canvas.drawBitmap() 方法无法正常工作

    我已经发布了两个与此相关的问题 请参考此自定义饼图 1 https stackoverflow com questions 28343600 customize pie chart in quarter shape at the botto
  • 使用 javascript 调整图像大小以在画布 createPattern 中使用

    我见过一些关于如何调整图像大小的技巧 在 IMG 标签内使用 但我想在里面有一个图像变量 一个 Javascript 调整它的大小 然后使用 a 中的图像 context createPattern 图像 重复 我还没有找到任何提示 关于如
  • Arbor Js - 节点 Onclick?

    我在用着arbor js http arborjs org 创建图表 我如何创建一个onclick节点的事件 或者在单击时在某处创建节点链接 Arborjs org 主页的节点在单击时链接到外部页面 我如何复制它 或者使节点在单击时调用 j
  • 如何在android中画一条曲线?

    我是 Android 新手 正在开发一个关于绘制线条的示例项目 我想画一条连接两点的曲线或高架线 x1 y1 and x2 y2 我试过canvas drawArc 方法 但是RectF内的值drawArc方法只是圆的 x y 中心点 它在
  • javascript ImageData 类型数组读取整个像素?

    所以有很多关于如何的例子writeImageData 对象的 Uint32Array 视图中的整个像素 但是是否可以在不将计数器增加 4 倍的情况下读取整个像素呢 从hacks mozilla org https hacks mozilla
  • 如何清除画布元素中的多边形区域?

    我使用过clearRect函数 但没有看到多边形的等效函数 我天真地尝试过 ctx fillStyle transparent ctx beginPath ctx moveTo 0 0 ctx lineTo 100 50 ctx lineT
  • FloorPlanner 应用程序的 SVG/Canvas 与 Flash

    我计划创建一个平面图应用程序 允许用户使用鼠标绘制 调整大小 移动和旋转对象 我只是想知道使用 Flash 或 Javascript 是否会更好 如果使用 Javascript 我应该使用 canvas 还是 SVG 该应用程序将允许拖动选
  • HTML5 canvas:有没有办法通过“最近邻居”重新采样来调整图像大小?

    我有一些 JS 对图像进行一些操作 我想要类似像素艺术的图形 所以我必须在图形编辑器中放大原始图像 但我认为用小图像进行所有操作然后使用 html5 功能放大它是个好主意 这将节省大量处理时间 因为现在my demo http anal s
  • 如何使用 AffineTransform.quadrantRotate 旋转位图?

    我想旋转一个bitmap关于它的中心点 然后将其绘制成更大的图形上下文 位图是40x40 pixels 图形上下文是500x500 pixels 这就是我正在做的 BufferedImage bi new BufferedImage 500
  • CreateJs Canvas 形状在 Windows Phone 上丢失坐标

    我正在制作一个 Createjs 和 html5 项目 在其中绘制一个形状 红色圆圈 当我单击圆圈时它会发出警报 它在所有台式机和 Android 手机上都能正常工作 除非我在 Windows Phone 中打开它 否则它在普通屏幕上工作正
  • 带滚动条的 HTML 画布

    我正在宽度不等的画布上绘制图表 每个画布可以有自己的滚动条吗 我尝试将所有画布放在一个 div 中并指定最大宽度 但它不起作用 是否有可能所有画布在页面上的可见宽度均为 500 像素 并且每个画布都有其滚动条来查看画布的整个宽度 谢谢 指定
  • 通过电子邮件发送在 HTML5 画布上创建的图像

    我有一个画布 用户可以通过交互来更改设计 现在 用户完成更改后 可以提交他的设计及其电子邮件 ID 但为了提交设计 我使用以下方法将画布转换为图像http www nihilogic dk labs canvas2image http ww
  • EaselJS Alpha 遮罩滤镜

    我对 Canvas 还很陌生 我一直在尝试将图像颠倒过来EaselJS Alpha 蒙版 http www createjs com demos easeljs alphamaskreveal示例 以便初始图像清晰 并且您可以paint是模
  • 如何在android中画分区的圆?

    我想在我的应用程序中绘制这种类型的圆圈 我可以使用 Canvas 绘制圆圈 但我不知道如何进行分区 谁能建议我如何分割圆 编辑 我想画内圈内的线 提前致谢 这是满足您要求的工作代码 编辑代码 Paint paint1 new Paint P
  • jsPlumb:如何使流程图连接器避免元素相交?

    是否可以使 jsPlumb Flowchart 连接器不交叉可连接的项目或指定元素 在示例中 具有 item 类的元素 默认流程图行为 想要的结果 这是我尝试过的 http jsfiddle net CcfTD 1 http jsfiddl
  • 将画布缩放到鼠标光标

    我正在编写一个 HTML5 项目 其中涉及使用滚轮放大和缩小图像 我想像谷歌地图一样缩放光标 但我完全不知道如何计算移动 我所拥有的 图像x和y 左上角 图像宽度和高度 光标 x 和 y 相对于画布中心 简而言之 你想要translate
  • Javascript 像素操作:这些不是我的颜色

    我知道类似的问题已经被问过好几次了 但我还没有找到我想要的东西 我正在将图像读入画布对象 在 JavaScript 中 并尝试操作一些特定的像素 例如 我正在寻找颜色 RGB 224 64 102 并尝试将其更改为其他颜色 我可以将灰度应用
  • 将 PictureStream 转换为 HTML5 画布

    我正在从 net Web 服务检索图片流的字节数组 JSON 字节数组响应如下所示 137 80 78 372 617 more 我正在尝试转换这个字节数组并将其绘制到 HTML 画布中 如下所示 var context document
  • 在overlayImage中应用滤镜的方法在哪里?

    我想在overlayImage中应用一个过滤器 唯一的方法是在渲染后在整个画布上应用过滤器 对此没有内置支持 但很容易 破解 var overlayImageUrl load overlay image first fabric Image
  • 在Android中绘制带有曲线底部的矩形视图

    美好的一天 我想画一个矩形作为视图 但底部应该是弯曲的 我不想应用这样的背景图像或使用任何视图 因为如果我使用视图并设置背景 曲线部分仍然会有不可见的空白空间 我将无法将另一个曲线图像附加到自定义视图的底部曲线 那么我该如何绘制一个带有底部

随机推荐

  • mysql数据库迁移到瀚高数据库,包含数据迁移、sql语法、服务启动、部署、tomcat问题整理

    文章目录 1 数据库迁移 2 数据库设置主键自增 2 1 数据库字段问题 2 2 存在即更新 2 3 清空数据表 2 4 瀚高数据库查询过程中显示转换 2 5 mybatis插入一条数据返回自增的主键值 2 6 瀚高数据库服务无法启动 3
  • 《数值分析》-- 雅可比迭代法、高斯—塞德尔迭代法

    文章目录 一 基本迭代法的格式及收敛性 1 1 迭代法思想 1 2 向量序列收敛的定义 二 迭代法的收敛与发散 三 雅可比迭代法和高斯赛德尔迭代法 3 1 雅可比迭代法 3 2 高斯 赛得尔 Gauss Seidel 迭代法 四 迭代法的收
  • python无法安装第三方库read time out_(python pip安装第三方库超时问题(raise ReadTimeoutErrorself._pool, None, 'Read time...

    python pip安装第三方库超时问题 raise ReadTimeoutErrorself pool None Read timed out pip工具安装 百度经验链接 pip安装及环境变量配置 pip下载超时处理 aise Read
  • Apache Shiro 简介

    本文转载自 点击打开链接 1 1 简介 Apache Shiro是Java的一个安全框架 目前 使用Apache Shiro的人越来越多 因为它相当简单 对比Spring Security 可能没有Spring Security做的功能强大
  • ztree 修改样式_zTree样式修改

    ztree挺好用的 不过公司美工设计的行政树图稿一般都比ztree原生的样式要好看的多 所以只能自己单独对样式进行修改 目前样式倒是修改好了 只能不能根据层级动态匹配样式 每个层级的被选中样式需要对两个属性单独设置 具体修改地方下面代码中有
  • java里%是什么_java里"."是什么意思?

    展开全部 lt 数学意义 在数字没有溢出的前提下 对于正数和负数 左移一位都相当于乘以2的1次方 左移n位就相当于乘以2的n次方 计算 3 lt lt 2 3 lt lt 2 则是将数字3左移2位 1 首先把3转换为二进制数字0000 00
  • python机器学习手写算法系列——逻辑回归

    从机器学习到逻辑回归 今天 我们只关注机器学习到线性回归这条线上的概念 别的以后再说 为了让大家听懂 我这次也不查维基百科了 直接按照自己的理解用大白话说 可能不是很严谨 机器学习就是机器可以自己学习 而机器学习的方法就是利用现有的数据和算
  • SQL11 高级操作符练习(1)

    描述 题目 现在运营想要找到男性且GPA在3 5以上 不包括3 5 的用户进行调研 请你取出相关数据 示例 user profile id device id gender age university gpa 1 2138 male 21
  • 牛客SQL练习一

    1 题目描述 查找最晚入职员工的所有信息 CREATE TABLE employees emp no int 11 NOT NULL birth date date NOT NULL first name varchar 14 NOT NU
  • springboot自定义favicon.ico

    先上效果图 1 在application yml文件中必须修改配置 spring mvc favicon enabled false spring mvc favicon enabled false 2 在static文件下 ico转化地址
  • LeetCode-Python-1248. 统计「优美子数组」(数组 + 数学)

    给你一个整数数组 nums 和一个整数 k 如果某个子数组中恰好有 k 个奇数数字 我们就认为这个子数组是 优美子数组 请返回这个数组中 优美子数组 的数目 示例 1 输入 nums 1 1 2 1 1 k 3 输出 2 解释 包含 3 个
  • base64格式图片展示

    后端发图片 为base64格式的 前端接收后页面展示图片 处理方法 let imageData data image png base64 res data image 后端传来数据 如果base64位图片没有带前面得头 data imag
  • clickhouse索引原理介绍

    clickhouse本身支持很多表引擎 这里只介绍其中最常用的MergeTree引擎 建表语句 name1 type1 DEFAULT MATERIALIZED ALIAS expr1 TTL expr1 name2 type2 DEFAU
  • cannot import name ‘Merge‘ from ‘keras.layers‘解决方法

    首先根据报错提示 找到对应的文件 看看Merge是否在keras layers里 发现现在已经改成下图的了 直接复制粘贴到代码里即可 报错提示为王 别再扎错方向
  • 数据清洗的基本流程_数据分析几步走?告诉你全面系统的流程

    通过对 谁说菜鸟不会数据分析 的阅读 我们知道数据分析的一般流程为 明确分析目标 一切以目标为导向 确定分析思路 数据获取 数据处理 清洗 转化 提取 计算等 数据分析及可视化 报表撰写 这就是数据分析的一般流程 本章我们就讲一下各个流程中
  • MySQl数据库必会sql语句(提升版)

    原文链接 http blog csdn net qq 32059827 article details 51778816 这一篇属于加强版 问题和sql语句如下 创建users表 设置id name gender sal字段 其中id为主键
  • 5V转1.8V稳压芯片,3.7V转1.8V稳压芯片

    5V转1 8V稳压芯片 3 7V转1 8V稳压芯片 5V转1 8V芯片 3 7V转1 8V芯片 5V转1 8V降压芯片 3 7V转1 8V降压芯片 5V转1 8V电路图 3 7V转1 8V电路图 锂电池3 7V输入和供电5V输入 降压转换成
  • 没有调试适配器,无法发送“variables”

    vs code调试报 没有调试适配器 无法发送 variables 今天在vs code调试node区块链应用时 点开打印内容 提示如上 并看不到打印内容 原因及解决方法 出现在这种情况是因为node调试比较特殊 执行调试完成之后进程退出
  • node接收文件

    目录 html nodejs详细实现 nodejs简单实现 html
  • 原生js + canvas 实现刻度尺效果

    欢迎访问我的 个人博客 手势事件 touchstart 手指按下 touchmove 手指移动 touchend 手指抬起 效果图 完整代码 ruler js var ruler 初始化刻度尺插件 el 容器 String height 刻