快应用-Canvas实现尺子左右滑动的效果
生活随笔
收集整理的這篇文章主要介紹了
快应用-Canvas实现尺子左右滑动的效果
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
完成效果:
在web頁面中,如果我們要實現左右滑動的效果,只需要在css中寫上:
overflow: hidden;
overflow-x: scroll;
就可以達到效果。但是在快應用中,不支持overflow命令。
所以這里用canvas畫圖來實現:監(jiān)聽手指左右滑動的事件,手指每滑動一次,重新繪制一次尺子 從而給人視覺上滑動的效果。
核心代碼:
template:
<div show="{{showRule}}" class="cover" @click="hideRule"></div><!-- 食物選擇尺寸 --><div show="{{showRule}}" class="Choice_count"><div class="date_title"><div class="date"><text class="dateText" >{{shortDate==today?'今天':shortDate.substr(0,4)+"年"+shortDate.substr(4,2)+"月"+shortDate.substr(6,2)+"日"}}</text></div><div class="images" @click="hideRule"><image src="../Common/icon_close.png" ></image></div></div><div class="food_detail" @click="goFoodDetailPage"><div class="food_info" ><image class="foodpic" src="{{!foodInfo.ImageUrl?'https://static.168play.cn/health/images/default.png':foodInfo.ImageUrl}}"></image><div class="food_text"><text class="fondname">{{foodInfo.FoodName}}</text><text class="num" style="margin-top:4px;">{{foodInfo.Calory}}千卡/{{foodInfo.Weight}}{{foodInfo.UnitName}}</text></div></div><div style="width:90px;height;160px;align-items: center;justify-content: center;" if="{{!foodInfo.IsCustom}}"><image style="height:25px;" src="../Common/degree_return.png"></image></div><div style="width:90px;height;160px;align-items: center;justify-content: center;" else><image style="height:36px;" src="../Common/food_modify.png"></image></div></div><div class="rule_module"><div class="amount_module"><text class="amount" >{{(weight_initParams.count*(weight_initParams.minScale)).toFixed(1)}}</text><text>{{activeUnitInfo.UnitName}}</text></div><div><text class="num">約{{((activeUnitInfo.Calory/activeUnitInfo.Amount)*(weight_initParams.count*(weight_initParams.minScale))).toFixed(1)}}千卡 {{((activeUnitInfo.Weight/activeUnitInfo.Amount)*(weight_initParams.count*(weight_initParams.minScale))).toFixed(1)}}{{foodInfo.UnitName}}</text></div><div class="ruler"><canvas class="new-canvas" id="weight-canvas" @touchmove="move('weight_initParams')" @touchstart="start('weight_initParams')" @touchend="end('weight_initParams')" ></canvas></div></div><div class="unitList"> <div for="{{foodUnitInfo}}" class="foodUnit" @click="changeUnit($idx)"><text class=" {{$item.UnitName==activeUnitInfo.UnitName?'unitActive':'unit'}}" >{{$item.UnitName}}</text></div></div><input class="button" type="button" value="確定" onclick="addFoodFromRule" /></div>Css:
.cover{width:100%;height: 100%;background-color: #000000;position: fixed;top: 0px;left: 0px;opacity: 0.7} .Choice_count{width: 100%;height:840px;position: fixed;bottom: 0;left: 0;background-color: #ffffff;flex-direction: column;border-top-left-radius:20px;border-top-right-radius:20px} .date_title{width:100%;height:120px;border-bottom: 1px solid #EAE5DD;align-items: center;}.dateText{font-size:36px;color: #473B1D;position:absolute;}.date{width:100%;height: 120px;position: relative;align-items: center;justify-content: center;}.foodUnit{width:140px;align-items: center;justify-content: center;}.foodUnit text{lines:1;text-overflow:ellipsis;}.button{background-color: #FFD359;width:100%;height: 105px;font-size: 32px;color: #473B1D;font-weight: bold;position:absolute;bottom: 0;left: 0;}.unitList{align-items:center;justify-content: center;}.unit{padding:10px,0;color:#473b1d;font-size: 32px;}.unitActive{padding:10px,0;color:#ffd359;font-weight:bold;font-size: 32px;}.amount_module text{color:#473b1d;font-weight:700}.amount_module{width:100%;justify-content:center;align-items:flex-end;font-family:'Microsoft YaHei';}.rule_module{width:100%;background-color:#fff;flex-direction:column;align-items: center;}.amount{font-size:72px;font-weight:700;position:relative;top:12px;margin-right:6px}.ruler{margin-top:6px}.new-canvas{margin-top:20px;height:200px;width:1000px}.food_detail{align-items: center;height:160px;justify-content:space-between;}.images{height: 120px;;position: absolute;right:20px;padding:20px;align-items: center}.images image{height:34px}script:
<script> export default {private: {shortDate: 0,today: 0,foodUnitInfo: [],//單位信息foodInfo: {},//食物信息activeUnitInfo: {},//當前單位activeAmount: 0,//當前數量winWidth: 1000,showRule: false,weight_initParams: {count: 0,lastX: 0,initX: 0, //初始x 距離endX: 0, //結束x 距離distanceX: 0, //移動距離distance_X: 0,// 判斷用的移動距離canvasID: 'weight-canvas',height: 200,maxScale: 100, //區(qū)間數minScale: 1, //最小刻度值start_scale: 0, //開始刻度數markColor: "#FFCC33",CanCheckStartAndEnd: false //可否選擇開始和結束的刻度}},onShow(){//展示尺子this.initRule(1);}//設置尺子的初始值initRule(num) {var me = this;var unit = me.activeUnitInfo.UnitNameme.weight_initParams.minScale = me.activeUnitInfo.MinVal;var initNum = 2;if (num == 0) {if (unit == '克' || unit == '毫升') {initNum = 100;console.log("初始值 " + initNum);me.weight_initParams.maxScale = 1000;me.weight_initParams.lastX = initNum;me.weight_initParams.count = initNum;me.drawRuler(initNum, 'weight_initParams');} else {console.log("初始值 " + initNum);me.weight_initParams.maxScale = 200;me.weight_initParams.lastX = initNum;me.weight_initParams.count = initNum;me.drawRuler(initNum, 'weight_initParams');}} else {if (unit == '克' || unit == '毫升') {me.weight_initParams.maxScale = 1000;} else {me.weight_initParams.maxScale = 200;}initNum = num;if (num >= 1000) {initNum = 999;}me.weight_initParams.maxScale = 200;me.weight_initParams.lastX = initNum;me.weight_initParams.count = initNum;me.drawRuler(initNum, 'weight_initParams');},drawRuler(count, class_initParams) {var me = this;count = count < 0 ? 0 : count;var initParams = eval(' me.' + class_initParams);var maxScale = initParams.maxScale;var minScale = initParams.minScale;var start_scale = initParams.start_scale;var currentWight = me.$page.query.weight;if (!initParams.CanCheckStartAndEnd) {if (count == 0) {count = 1;}if (count == maxScale) {count = maxScale - 1;}}eval('me.' + class_initParams + '.count= count');var winWidth = this.winWidth;count = count - 20.75;//刻度值數組const canvas = this.$element(initParams.canvasID) //獲取 canvas 組件const cxt = canvas.getContext('2d') //獲取 canvas 繪圖上下文const img = new Image() //新建圖像對象//清空畫布// cxt.clearRect(0, 0, winWidth, initParams.height);img.src = '../Common/ruler.png' //加載本地圖片//加載成功的回調img.onload = () => {//清空畫布cxt.clearRect(0, 0, 1000, initParams.height);for (var i = 0; i < (maxScale / 10); i++) {var ynum = (count * -24) + (i * 240);if (ynum > -100 && ynum < 800) {cxt.drawImage(img, (count * -24) + (i * 240), 0);}if (ynum > 1000) {break;}var num = ((minScale * i * 10) + start_scale).toFixed(0); //刻度尺cxt.beginPath();cxt.save();cxt.font = " small-caps bold 50px aria";cxt.fillStyle = initParams.color ? initParams.color : "#C1BDB3";cxt.textAlign = "center";cxt.textBaseline = "middle";cxt.fillText(num.toString(), (count * -24) + (i * 240), 160);cxt.closePath();// cxt.drawImage(img, (count * -23)+(i*227), 0, 230, 140);}if (maxScale % 10 == 0) {var num = ((maxScale + start_scale) * minScale).toFixed(0);cxt.beginPath();cxt.save();// cxt.font = "50px ALIBABAFont-Bold";cxt.font = " small-caps bold 50px aria";cxt.fillStyle = initParams.color ? initParams.color : "#C1BDB3";cxt.textAlign = "center";cxt.textBaseline = "middle";cxt.fillText(num.toString(), (count * -24) + (i * 240), 160);cxt.closePath();}//中心刻度線this.onceDrawRuler(class_initParams);},onceDrawRuler(class_initParams) {var me = this;var winWidth = this.winWidth;var initParams = eval('me.' + class_initParams);//刻度值數組var division = winWidth / 50; //每個刻度的距離 分割線const canvas = this.$element(initParams.canvasID) //獲取 canvas 組件const cxt = canvas.getContext('2d') //獲取 canvas 繪圖上下文//畫橫線cxt.beginPath();cxt.strokeStyle = "#EAE5DD";cxt.lineWidth = 1;cxt.lineCap = "round";cxt.moveTo(0, 5);cxt.lineTo(1200, 5);cxt.stroke();cxt.restore();cxt.closePath();//中心刻度線cxt.beginPath();cxt.save();cxt.strokeStyle = initParams.markColor;cxt.lineWidth = 1;cxt.lineCap = "round";var height = 200 * Math.sin(Math.PI / 3);//計算等邊三角形的高cxt.moveTo((winWidth / 2), 17); //從A(100,0)開始cxt.lineTo((winWidth / 2) - 14, 4);//從A(100,0)開始,畫到B (0,173)結束cxt.lineTo((winWidth / 2) + 14, 4); //B(0,173)-C(200,173)//cxt.fillStyle='#00ff00';//以純色綠色填充var grd = cxt.createLinearGradient(0, 0, 200, 0);//使用漸變顏色填充,從(0,0)到(200,0) (左到右)grd.addColorStop(0, initParams.markColor); //起始顏色grd.addColorStop(1, initParams.markColor); //終點顏色cxt.fillStyle = grd; //以上面定義的漸變填充cxt.fill(); //閉合形狀并且以填充方式繪制出來cxt.stroke();cxt.restore();cxt.beginPath();cxt.save();cxt.strokeStyle = initParams.markColor;cxt.lineWidth = 5;cxt.lineCap = "round";cxt.moveTo((winWidth / 2), 6);cxt.lineTo((winWidth / 2), 118);cxt.stroke();cxt.restore();cxt.closePath();},//刻度尺 相關邏輯end(class_initParams) {var me = this;var count = eval('this.' + class_initParams + '.count');var lastX = eval('this.' + class_initParams + '.lastX');// //目標體重不能跟 現在體重一致if (class_initParams == 'weight_initParams') {if (count < me.maxCount && count > me.miniCount) {var animate_rate = 0;if (count <= lastX) {// var diffcount= count-me.miniCount;// let myFunction = setInterval(() => {// animate_rate += 0.01;// me.drawRuler(count +diffcount*animate_rate, class_initParams)// }, 5)// setTimeout(function () { clearInterval(myFunction); }, 2000);count = me.miniCount;eval('me.' + class_initParams + '.count=count');} else {count = me.maxCount;eval('me.' + class_initParams + '.count=count');}if (class_initParams == 'weight_initParams') {me.drawRuler(count, class_initParams)}}eval('me.' + class_initParams + '.lastX=me.' + class_initParams + '.count');} else {eval('me.' + class_initParams + '.lastX=me.' + class_initParams + '.count');}},start(class_initParams, e) {eval('this.' + class_initParams + '.initX = e._touches[0].pageX;')},move(class_initParams, e) {eval(' this.' + class_initParams + '.endX = e._touches[0].pageX;');this.moveEvent(class_initParams);},moveEvent(class_initParams) {var me = this;var initParams = eval('me.' + class_initParams);var winWidth = this.winWidth;eval('this.' + class_initParams + '.distanceX= Math.floor((initParams.endX - initParams.initX) / (winWidth / 50));');initParams = eval('me.' + class_initParams);if (initParams.distanceX === initParams.distance_X) {return false;}eval('this.' + class_initParams + '.distance_X= initParams.distanceX;');eval('this.' + class_initParams + '.count = initParams.lastX - initParams.distanceX;');if (initParams.count >= initParams.maxScale || initParams.count <= 0) {eval('this.' + class_initParams + '.count = initParams.count >= initParams.maxScale ? initParams.maxScale : 0;');}this.drawRuler(eval('this.' + class_initParams + '.count'), class_initParams);}} </script>代碼中
img.src = ‘…/Common/ruler.png’ //加載本地圖片
…
cxt.drawImage(img, (count * -24) + (i * 240), 0); //繪制圖片
圖片如下:
在剛開始實現尺子效果時,我并沒有用到圖片來畫,是用canvas的畫筆 line 線條來畫的尺子,每滑動一次,就用線條繪制整個尺子效果,很耗性能,畫面非常卡頓。后來再做優(yōu)化的時候,嘗試通過借助圖片來畫,可以流暢運行。
這里貼上的代碼,是我從項目里摘出來實現尺子效果的核心代碼,并不能直接運行。僅供一個實現思路和流程。
總結
以上是生活随笔為你收集整理的快应用-Canvas实现尺子左右滑动的效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 物超所值的优化mysql_CXT UNO
- 下一篇: CCRC信息安全服务资质认证流程图及申报