老师 这里的circlie[i].y的取值有点看不懂
来源:9-3 完成案例动画部分
吾怯二日
2020-07-25 18:27:55
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>canvas绘制明信片</title>
<link rel="stylesheet" href="./cs/index.css">
</head>
<body>
<div class="container">
<div class="userInfo">
<div class="line">
<input type="text" id="username" placeholder="姓名">
</div>
<div class="line">
<input type="text" id="address" placeholder="地址">
</div>
<div class="line">
<input type="text" id="job" placeholder="职业">
</div>
<div class="line">
<input type="text" id="slogan" placeholder="口号">
</div>
<div class="line">
<button id="btn">生成名片</button>
</div>
</div>
<div class="userCard">
<canvas id="cardCanvas" style="display: none;">
您的浏览器不支持canvas
</canvas>
<canvas id="animCanvas">
您的浏览器不支持canvas
</canvas>
</div>
</div>
<script type="text/javascript" src="./js/index.js"></script>
</body>
</html>
CSS
* {
margin: 0;
padding: 0;
}
body,html {
overflow-x: hidden;
overflow-y: hidden;
min-width:1100px;
}
.container {
width: 80%;
height: 400px;
margin:0 auto;
margin-top: 140px;
}
.userInfo {
width: 30%;
height: 300px;
float: left;
background: #a4a296;
}
.userInfo .line {
margin-top: 20px;
text-align: center;
}
.userInfo .line input {
display: block;
height: 30px;
width: 80%;
margin: 0 auto;
border-radius: 15px;
text-indent: 10px;
border: none;
outline: none;
}
.line:first-child{
margin-top: 40px;
}
.line button {
display: block;
width: 100px;
height: 30px;
line-height: 30px;
outline: none;
border: none;
border-radius: 15px;
background: #222;
color: #ddd;
margin: 0 auto;
margin-top: 20px;
position: relative;
}
.line button:hover {
cursor: pointer;
left: 1px;
top: 1px;
}
.line button:active {
left: 1px;
top: 1px;
}
.userCard {
width: 70%;
height: 300px;
float: left;
background: #eee9d3;
position: relative;
}
.userCard #animCanvas {
height: 100px;
position: absolute;
top:80px;
left: 50%;
margin-left: -300px;
}
JS
//alert(1);
var cardCanvas = document.getElementById("cardCanvas"),
cardContext = cardCanvas.getContext("2d");
cardCanvas.width = 600;
cardCanvas.height = 100;
var myImg = new Image();
myImg.src = "./img/logo.png";
myImg.onload = function(){
cardContext.drawImage(myImg,10,10);
}
var btn = document.getElementById("btn");
btn.onclick = function(){
cardContext.clearRect(0,0,600,100);
//背景渐变
var linearGradient = cardContext.createLinearGradient(0,0,600,100);
linearGradient.addColorStop(0.5,"rgb(0,0,0)");
linearGradient.addColorStop(1,"rgb(133,133,133)");
cardContext.fillStyle = linearGradient;
cardContext.fillRect(0,0,600,100);
//logo绘制
cardContext.drawImage(myImg,10,10);
var name = document.getElementById("username").value || "请输入姓名";
var address = document.getElementById("address").value || "请输入地址";
var job = document.getElementById("job").value || "请输入工作";
//获取三条信息文字的长度 得到最长的长度 以确定口面口号的位置
var nameWidth,addressWidth,jobWidth,maxWidth=0;
cardContext.font = "bold 30px sans-serif";
cardContext.fillStyle = "#fff";
cardContext.fillText(name,105,35);
nameWidth = cardContext.measureText(name).width;
cardContext.font = "bold 20px sans-serif";
cardContext.fillText(address,105,60);
addressWidth = cardContext.measureText(address).width;
cardContext.fillText(job,105,85);
jobWidth = cardContext.measureText(job).width;
//获取最长信息的文字宽度
if(maxWidth<nameWidth){
maxWidth = nameWidth;
}
if(maxWidth<addressWidth){
maxWidth = addressWidth;
}
if(maxWidth<jobWidth){
maxWidth = jobWidth;
}
//绘制口号
var slogan = document.getElementById("slogan").value || "请输入口号";
cardContext.save();
//图形变换
cardContext.rotate(-0.1);
cardContext.translate(0,50);
// 阴影
cardContext.shadowOffsetX = 10;
cardContext.shadowOffsetY = 10;
cardContext.shadowColor = 'rgba(0, 0, 0, 0.5)';
cardContext.shadowBlur = 1.5;
cardContext.fillStyle = "#ddd";
//计算口号位置
var sloganWidth;
sloganWidth = cardContext.measureText(slogan).width;
var offset = ( cardContext.canvas.width - 115 - maxWidth - sloganWidth)/2;
var sloganX = 115 + maxWidth + offset;
cardContext.fillText( slogan , sloganX , 50 );
//绘制曲线
cardContext.beginPath();
cardContext.moveTo(sloganX , 70);
cardContext.quadraticCurveTo( sloganX , 50 , sloganX + sloganWidth ,60);
cardContext.strokeStyle = "#ffffff";
cardContext.stroke();
cardContext.restore();
}
btn.click();
/*
思路
一共同时填充10个圆 这些圆的半径范围1-5 Math.floor(Math.random()*5)+1
通过循环 给circle 添加这10个对象
在第一次循环中 添加了10个对象 我们需要在单个对象绘制到animCanvas底部时重新绘制一个新的圆
所以 依据circle中是否存在要绘制的单个对象来判断是否重制这个圆 或者只是增加它的Y坐标值达到动画效果
初始不存在 创建这个对象 所以if中判断的是这个对象是否存在
如果存在 进行if后的语句 通过vx递增它的绘制圆心Y值
如果其绘制点Y方向值大于animCanvas的height+圆的直径(同样为了使圆自然的滑出animCanvas画布) 设置其值为undefined/null
重新在绘制该索引对应的圆
为了达到单个圆自然的进出animCanva 它真实的运动范围是一个animCanvas宽+圆半径*2 animCanvas高+圆半径*2 的矩形
创建单个圆对象的过程
通过循环 为其添加 绘制点X坐标值 Y坐标值 半径值 达到动画效果的Vx递增值
*/
//获取animCanvas 动画绘制的canvas
var animCanvas = document.getElementById("animCanvas"),
animContext = animCanvas.getContext("2d");
animCanvas.width = 600;
animCanvas.height = 100;
var circle = [];//用来存放所有绘制的动态圆
setInterval(function(){
animContext.clearRect(0,0,animCanvas.width,animCanvas.height);
animContext.drawImage(cardCanvas,0,0,animCanvas.width,animCanvas.height,0,0,cardCanvas.width,cardCanvas.height);
for(let i=0;i<=10;i++){
if(!circle[i]){
circle[i] = {};
circle[i].r = Math.floor(Math.random()*5) + 1;//半径取值范围1-5
circle[i].x = 60*i + Math.floor(Math.random()*10) - 5;
circle[i].y = -circle[i].r - Math.floor(Math.random()*10);//circle[i].y = -circle[i].r;
circle[i].vx = Math.floor(Math.random()*5) + 1;//圆递y方向递增取值范围1-5
}
//console.log(circle[i]);
animContext.beginPath();
animContext.arc(circle[i].x, circle[i].y, circle[i].r, 0, Math.PI*2, true);
animContext.fillStyle = "rgba(255,255,255,0.5)";
animContext.fill();
circle[i].y = circle[i].y + circle[i].vx;
if(circle[i].y > animCanvas.height + circle[i].r*2){
circle[i] = null;
}
}
},100)
问题: 这里关于circle[i].y的取值 好像只要是小于-5的任意值都可以 或者是-圆半径也可以 老师这里写的是什么意思呢 距离写的这么远是为什么呀
1回答
同学你好,同学的想法直接设置circle[i].y = -circle[i].r也是可以实现效果的,老师这种写法是为了单独计算一个随机数,距离写的稍微远一点,方便更加容易看到效果。
同学重点是了解下实现思路就可以了,实际开始用在结合实际应用场景灵活运用所学知识就可以了。
祝学习愉快~
相似问题
回答 5