先看一下最終效果


正弦曲線

正弦曲線公式 y = A sin(Bx + C) + D
振幅是 A,A 值越大,曲線更陡峭
B值越大 周期越短
C水平位移
垂直位移是 D,控制曲線上下移動
實作思路
首先來繪制曲線
1.定義建構式和初始化方法
//sin曲線建構式
function drawSin(option){
this.init(option);
}
//初始化
drawSin.prototype.init=function(o){
this.A=6;//振幅
this.B=0.02;//周期
this.C=0;//水平位移
this.D=H/2;//垂直位移
this.color='orange';//填充顏色
this.speed=-0.2; //移動速度
this.percent=0;//百分比
this.offsetX=0;//開始X坐標
for(var key in o){//回圈new時候傳入的引數,如果存在,則覆寫,沒有傳則使用默認
if(typeof this[key] !=='undefined'){
this[key] = o[key];
}
}
}
2.添加一個render繪制函式
//繪制曲線
drawSin.prototype.render=function(c){
c.save();
c.beginPath();
var y=0;
for(var x=this.offsetX;x<W+this.offsetX;x+=0.01){
//正弦曲線公式:y = A sin(Bx + C) + D
//振幅是 A,A 值越大,曲線更陡峭
//B值越大 周期越短
//C水平位移
//垂直位移是 D,控制曲線上下移動
y = this.A*Math.sin(this.B*(x+this.offsetX) + this.C) + this.D;
c.lineTo(x,y);
}
c.lineTo(W,H);
c.lineTo(0,H);
c.fillStyle = this.color;
c.stroke()
c.closePath();
c.restore();
return this;
}
3.生成一根正弦曲線
var sin1 = new drawSin({
A:20,B:0.025,
C:0,D:H/2-6,
color:'#3399FF'
}).render(ctx);
4.看一下現在的效果

5.加上流動代碼
drawSin.prototype.update=function(){
this.C+=this.speed;//設定橫向移動遞增
}
function move(){
//執行影片幀
window.requestAnimationFrame(move);
//清理畫布
ctx.clearRect(0,0,W,H);
//更新
sin1.update();
//繪制
sin1.render(ctx);
}
window.requestAnimationFrame(move);

6.加上顏色

裁剪成圓形
draw();
function draw(){//畫圓
ctx.strokeStyle='rgb(250,235,215)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.arc(W/2,H/2,160,0,Math.PI*2,true);
ctx.stroke();
ctx.clip();
}
效果如下

加上百分比
<canvas id='canvas'></canvas>
<div id='percent'>
<input type='text' value=0 oninput="doInput(this)" style="display:none;" >
<p style="text-align: center;color:orange;"></p>
</div>
//顯示的百分比
function text(val){
if(inputClick)return ;
percent.children[1].innerText=val;
percent.children[0].value=val;
}
function doClick(e){
var p=percent.children[1],input=percent.children[0];
var e=e||window.event;
var target=e.currentTarget;
e.stopPropagation();//阻止冒泡
if(target.tagName&&target.tagName.toUpperCase()==='DIV'){
if(input.style.display==''){
return;
}
//顯示input
input.style.display='';
p.style.display='none';
input.value=p.innerText;
input.focus();
inputClick=true;
}else{
if(input.style.display==''){
p.style.display='';
//隱藏input
input.style.display='none';
p.innerText=input.value;
//處理百分比
editPercent();
}
}
}
function editPercent(){
var p=percent.children[1],input=percent.children[0];
//執行影片
sin1.change=parseInt(p.innerText);
sin2.change=parseInt(p.innerText);
}
//控制文本輸入
function doInput(obj){
obj.value=obj.value.replace(/[^\d]/g,'');
if(obj.value=='')obj.value=0;
var value = parseInt(obj.value);
if(value>100){
obj.value=100;
}else if(value<=0){
obj.value=0;
}
}
//百分比點擊事件
percent.addEventListener('click',doClick);
document.addEventListener('click',doClick);
看下效果

加多一條曲線、百分比可以編輯就完成了
換其他圖形試試
1.三角形

2.長方形

3.心形

全部代碼:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="GBK">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
canvas{
left:30px;
position: absolute;
border:1px solid ;
}
#percent{
width: 90px;
height: 90px;
position: absolute;
left: 190px;
top: 230px;
font-size: 50px;
cursor: pointer;
}
#percent input{
width: 90px;
height: 90px;
border-radius: 10px;
border: 1px solid #EEEEEE;
text-align:center;
font-size: 50px;
}
</style>
</head>
<body>
<canvas id='canvas'></canvas>
<div id='percent'>
<input type='text' value=0 oninput="doInput(this)" style="display:none;" >
<p style="text-align: center;color:orange;"></p>
</div>
<script type="text/javascript">
var percent = document.getElementById('percent');
var canvas = document.getElementById('canvas')
var W = canvas.width = 400
var H = canvas.height = 400
var ctx = canvas.getContext('2d');
var inputClick=false;//控制百分比內容是否可以被更新
draw();
function draw(){//畫圓
ctx.strokeStyle='rgb(250,235,215)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.arc(W/2,H/2,160,0,Math.PI*2,true);
ctx.stroke();
ctx.clip();
}
//drawTriangle();
function drawTriangle(){//畫三角形
ctx.strokeStyle='rgb(250,235,215)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.moveTo(W/2,40);
ctx.lineTo(100,360);
ctx.lineTo(300,360);
ctx.closePath();
ctx.stroke();
ctx.clip();
}
//drawRect();
function drawRect(){//畫方形
ctx.strokeStyle='rgb(250,235,215)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.rect(140,40,120,320);
ctx.closePath();
ctx.stroke();
ctx.clip();
}
//drawHeart();
function drawHeart(){//畫心形
ctx.strokeStyle='rgb(250,235,215)';
ctx.lineWidth=10;
ctx.beginPath();
ctx.lineCap='round';
ctx.moveTo(200, 100);
ctx.bezierCurveTo(50,-120,-80,260, 200, 360);
ctx.moveTo(200, 100);
ctx.bezierCurveTo(350,-120,W+80,260, 200, 360);
ctx.stroke();
ctx.clip();
}
//sin曲線建構式
function drawSin(option){
this.init(option);
}
//初始化
drawSin.prototype.init=function(o){
this.A=6;//振幅
this.B=0.02;//周期
this.C=0;//水平位移
this.D=H/2;//垂直位移
this.color='orange';//填充顏色
this.speed=-0.2; //移動速度
this.percent=0;//百分比
this.offsetX=0;//開始X坐標
this.moveFlag=false;//頁面加載時是否執行移動影片
this.move={//定義移動影片的相關引數
start:360,//開始位置
end:200,//結束位置
total:320,//總高度
dis:40,//距離畫布底部的高度
speed:4//美移動影片速度
};
for(var key in o){//回圈new時候傳入的引數,如果存在,則覆寫,沒有傳則使用默認
if(typeof this[key] !=='undefined'){
this[key] = o[key];
}
}
if(this.moveFlag){//如果有移動標示,則sin曲線的Y位置更新為初始位置
this.D=this.move.start;
}else {//否則執行更新函式
this.update();
}
}
drawSin.prototype.update=function(){
this.C+=this.speed;//設定橫向移動遞增
if(typeof this.change=='number'){//這個是修改百分比執行的更新塊
var temp = this.change*this.move.total/100;//計算當前百分比應該占用總高度的實值
var changePos=this.move.start-temp;//計算應該處于的位置
if(changePos>this.move.end){//水波往下
this.D+=this.move.speed;
if(this.D>=changePos){//執行到位置后釋放相關引數
this.change=undefined;
this.move.end=this.D;//設定結束位置
inputClick=false;
}
}else if(changePos<this.move.end){
this.D-=this.move.speed;
if(this.D<=changePos){
this.change=undefined;
this.move.end=this.D;
inputClick=false;
}
}else {
this.change=undefined;
inputClick=false;
}
//設定最終百分比
this.percent = this.change;
}else{
if(this.moveFlag && this.D>this.move.end){//如果沒有執行到終點,就繼續執行
this.D-=this.move.speed;
}
//設定百分比
this.percent =Math.round((this.move.total+this.move.dis-this.D)/this.move.total*100);
//顯示百分比
text(this.percent);
}
}
//繪制曲線
drawSin.prototype.render=function(c){
c.save();
c.beginPath();
var y=0;
for(var x=this.offsetX;x<W+this.offsetX;x+=0.01){
//正弦曲線公式:y = A sin(Bx + C) + D
//振幅是 A,A 值越大,曲線更陡峭
//B值越大 周期越短
//C水平位移
//垂直位移是 D,控制曲線上下移動
y = this.A*Math.sin(this.B*(x+this.offsetX) + this.C) + this.D;
c.lineTo(x,y);
}
c.lineTo(W,H);
c.lineTo(0,H);
c.fillStyle = this.color;
c.fill();
c.closePath();
c.restore();
return this;
}
//顯示的百分比
function text(val){
if(inputClick)return ;
percent.children[1].innerText=val;
percent.children[0].value=val;
}
//創建sin曲線1
var sin1 = new drawSin({
A:10,B:0.025,
C:0,D:H/2-6,
color:'#3399FF',
speed:-0.1,
moveFlag:true
}).render(ctx);
//創建sin曲線2
var sin2 = new drawSin({
A:10,B:0.025,
C:0,D:H/2,
color:'#3366FF',
speed:-0.1,
offsetX:40,
moveFlag:true
}).render(ctx);
function move(){
//執行影片幀
window.requestAnimationFrame(move);
//清理畫布
ctx.clearRect(0,0,W,H);
//更新
sin1.update();
//繪制
sin1.render(ctx);
sin2.update();
sin2.render(ctx);
}
window.requestAnimationFrame(move);
function doClick(e){
var p=percent.children[1],input=percent.children[0];
var e=e||window.event;
var target=e.currentTarget;
e.stopPropagation();//阻止冒泡
if(target.tagName&&target.tagName.toUpperCase()==='DIV'){
if(input.style.display==''){
return;
}
//顯示input
input.style.display='';
p.style.display='none';
input.value=p.innerText;
input.focus();
inputClick=true;
}else{
if(input.style.display==''){
p.style.display='';
//隱藏input
input.style.display='none';
p.innerText=input.value;
//處理百分比
editPercent();
}
}
}
function editPercent(){
var p=percent.children[1],input=percent.children[0];
//執行影片
sin1.change=parseInt(p.innerText);
sin2.change=parseInt(p.innerText);
}
//控制文本輸入
function doInput(obj){
obj.value=obj.value.replace(/[^\d]/g,'');
if(obj.value=='')obj.value=0;
var value = parseInt(obj.value);
if(value>100){
obj.value=100;
}else if(value<=0){
obj.value=0;
}
}
//百分比點擊事件
percent.addEventListener('click',doClick);
document.addEventListener('click',doClick);
</script>
</body>
</html>
給個三連吧大佬們,謝謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/254113.html
標籤:其他
下一篇:Web前端之CSS
