歡迎訪問我的 個人博客
手勢事件
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 | 否 | 返回此刻的值 |