需求描述:用css
的transparent属性
渲染三角形和梯形,根据传入的参数,动态渲染类金字塔结构的图形。如下:
<style>
/* 三角形 */
#Triangle{
width: 0px;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 30px solid grey;
}
/* 梯形 */
#Trapezoid{
width: 10px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 30px solid grey;
}
</style>
<!-- 一个简单的三角形 -->
<div id="Triangle"></div>
<!-- 一个简单的梯形 -->
<div id="Trapezoid"></div>
效果如下:
分析过程:(设第n个图形的上底为Xn,下底为Yn,高恒为h,两个图形之间的距离恒为d,倾斜角度为α)
则css的属性值与图形各个长度的对应关系为:
width: (Xn)px;
height: (d)px;
border-left: (t)px solid transparent;
border-right: (t)px solid transparent;
border-bottom: (h)px solid grey;
/* 相关计算公式如下:
t = (Yn - Xn)/ 2
tanα = t / h
*/
需由上关系推出Xn,Yn与用户已输入的参数之间的关系:
- 当n = 1,X1 = x, Y1 = y,t = (Y1-X1) / 2
- 当n = 2,X2 = Y1 + (2td) / h,Y2 = X2 + 2t,t2 = t1
- 当n = 3,X3 = Y2 + (2td) / h,Y3 = X3 + 2t,t3 = t1
- …
- Xn = Y(n-1) + (2td) / h, Yn = Xn + 2t, tn = t1
- 由此得出状态公式:
若n = 1,Xn = x,Yn = y,tn = (y-x) * 0.5
若n > 1,Xn = Y(n-1) + ((y-x) * d) / h,Yn = Xn + (y-x),tn = (y-x) * 0.5
完整详细代码如下:
<html lang="en">
<head>
<title>算法【动态规划】——前端实践:类金字塔</title>
</head>
<style>
/* 分割线 */
.divider{
width: 100%;
height: 10px;
}
/* 平行四边形 */
#Paralle{
width: 30px;
height: 20px;
background-color: grey;
transform: skew(-25deg);
}
/* 三角形 */
#Triangle{
width: 0px;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 30px solid grey;
}
/* 梯形 */
#Trapezoid{
width: 10px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 30px solid grey;
}
/* 比例: 4 height:10px width:【30, 50, 70, 90, 110, 130, 150】 border-bottom:30px border-left:7.5px*/
/* 比例:3.5 height:12px width:【40, 64, 88, 112, 136, 150, 174】border-bottom:30px border-left:8.6px*/
/* 类金字塔 */
#Pyramid{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
<body>
<!-- 平行四边形 -->
<div id="Paralle"></div>
<!-- 分隔间距 -->
<div class="divider"></div>
<!-- 三角形 -->
<div id="Triangle"></div>
<!-- 分隔间距 -->
<div class="divider"></div>
<!-- 梯形 -->
<div id="Trapezoid"></div>
<!-- 分隔间距 -->
<div class="divider"></div>
<!-- 类金字塔 -->
<div id="Pyramid"></div>
</body>
<script>
window.onload = this.drawPyramid({
x: 0, //第一个图形的上底(较短的边),为0时表示第一个图形为三角形
y: 20, //第一个图形的下底(较长的边)
h: 10, //图形的高
d: 5, //相邻图形之间的距离
start: 1, // 从第几个图形开始渲染
account: 7, // 生成图形盒子总的个数
inverted: false, // 是否倒金字塔
});
/**
* 开始生成 box DOM节点
* @param { account } 生成图形盒子总的个数
* 第一个图形:上底(x) 下底(y), 高(h), 两个相邻邻图形之间的距离(d), 半下底-半上底(t)
* inverted: true-'倒金字塔' false-'正金字塔'
*/
function drawPyramid({account=1, inverted=false, x=0, y=20, h=10, d=5, start=1}){
let dom = document.getElementById("Pyramid");
if(!dom || account<1 || x<0 || y<0 || y<=x || h<0 || start < 1) return ; // 异常处理
let arr = []; // 存放各个图形的属性值
let lastX = x, lastY = y, t = (y-x) * 0.5;
for(let i = start-1; i < account+start; ++i){ // 正逆序金字塔属性处理
let Xn = lastX, Yn = lastY ;
if( i != 0) {
Xn = lastY + ((y-x)*d)/h; // 根据上一个图形的状态得到当前状态的值
Yn = Xn + (y-x); // 根据上一个图形的状态得到当前状态的值
}
lastX = Xn;lastY = Yn; // 保留当前图形的状态
const obj = { t, h, d, width: Xn, height: Yn};
inverted ? arr.unshift(obj) : arr.push(obj)
}
// 渲染图形
arr.forEach(item => {
let divBox = document.createElement('div');
let styleObj = {
'width': item.width + 'px',
'height': item.d + 'px',
'border-left': item.t + 'px' + ' solid transparent',
'border-right':item.t + 'px' + ' solid transparent',
'border-top': inverted ? item.h + 'px' + ' solid grey' : 0,
'border-bottom': inverted ? 0 : item.h + 'px' + ' solid grey',
}
let str = Object.keys(styleObj).reduce((prev, cur) => prev + cur + ':' + styleObj[cur] +';' ,'');
divBox.style.cssText = str
dom.appendChild(divBox)
})
}
</script>
</html>