HarmonyOS 鸿蒙Next Matrix4倾斜变换,立体盒子动画,API 9
HarmonyOS 鸿蒙Next Matrix4倾斜变换,立体盒子动画,API 9
OpenHarmony 文档 @ohos.matrix4 (矩阵变换)
其中倾斜功能skew要到API12以后才提供,但是只要知道了矩阵变换原理,也可以手搓倾斜
首先说明一下OH 中 Matrix4(4阶矩阵)的参数位置。
斜着的sx,sy,sz代表xyz轴缩放倍数,为1表示不缩放。
最下面的dx,dy,dz代表xyz轴位移。
除了右侧三个0,前面的0,官网的解释是跟xyz旋转有关。
jx和jy是相对于xy轴夹角的正切。
"?"是很诡异的存在,大家可以自己尝试一下。
官网关于这个变换的说明太模糊了。虽然提供了一些基本变换功能,但是关于矩阵计算这个强大的能力,几乎没有什么说明。
最终效果如下:
import matrix4 from ‘@ohos.matrix4’;
import curves from ‘@ohos.curves’;
@Entry
@Component
struct Matrix4 {
zk左宽=60
yk右宽=120
g高=40
jd角度1=25
py平移1=(this.g高/2)Math.tan(this.jd角度1Math.PI/180)
dg顶高=this.zk左宽*Math.sin(2this.jd角度1Math.PI/180)
py平移顶1=(this.dg顶高/2)Math.tan((90-2this.jd角度1)*Math.PI/180)
xb斜边=this.g高/Math.cos(this.jd角度1*Math.PI/180)
jd角度2=-this.jd角度1
py平移2=(this.g高/2)/Math.tan(this.jd角度2*Math.PI/180)
zq正切1=Math.tan(this.jd角度1*Math.PI/180)
//向左水平倾斜
zq左切=Math.tan(this.jd角度1*Math.PI/180)
jz矩阵左平倾斜=matrix4.init([
//x轴比例,y斜切,?(值越大,越正交斜切),x
1.0, 0.0, 10.0, 0.0,
//x斜切,Y轴缩放,?,x
this.zq左切, 1.0, 0.0, 0.0,
//?(值越大,越正交斜切),?,z轴缩放,x
0.0, 0.0, 1.0, 0.0,
//x轴平移,y轴平移,z轴平移,齐次坐标下透视投影
0.0, 0.0, 0.0, 1.0])
//向右水平倾斜
yq右切=Math.tan(this.jd角度2*Math.PI/180)
jz矩阵右平倾斜=matrix4.init([
1.0, 0.0, 10.0, 0.0,
this.yq右切, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0])
//向左水平倾斜
gq高切=Math.tan((90-2this.jd角度1)Math.PI/180)
jz高=matrix4.init([
1.0, 0.0, 10.0, 0.0,
this.gq高切, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0])
//向右水平倾斜
jz矩阵右上倾斜=matrix4.init([
1.0, -Math.tan(this.jd角度1*Math.PI/180), 200, 0.0,
0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0])
@State dq当前:number=0
@State z:number=0
bj背景色:string= ‘#fff67e15’
bj背景色2:ResourceStr= ‘#ff0ebbff’
@Builder hz盒子(z:number){
Stack(){
<span class="hljs-comment"><span class="hljs-comment">//上盖</span></span>
Row(){
Row()
.width(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.yk右宽).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dg顶高)
.backgroundColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色<span class="hljs-number"><span class="hljs-number">2</span></span> : <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色)
.brightness(<span class="hljs-number"><span class="hljs-number">1.2</span></span>)
.transform(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jz高)
.onClick(()=>{<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dj点击盒子(z)})
<span class="hljs-comment"><span class="hljs-comment">// .onTouch((e)=>{e.stopPropagation})</span></span>
<span class="hljs-comment"><span class="hljs-comment">// .border({width:1,color: '#fffaffff' })</span></span>
}<span class="hljs-comment"><span class="hljs-comment">//.zIndex(0)</span></span>
.translate({x:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽 - <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移顶<span class="hljs-number"><span class="hljs-number">1</span></span>,y:-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-number"><span class="hljs-number">1</span></span>})
.rotate({z:<span class="hljs-number"><span class="hljs-number">1</span></span>,angle:-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>+<span class="hljs-number"><span class="hljs-number">0.09</span></span>,centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移顶<span class="hljs-number"><span class="hljs-number">1</span></span>,centerY:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dg顶高})
<span class="hljs-comment"><span class="hljs-comment">//左右</span></span>
Row() {
<span class="hljs-comment"><span class="hljs-comment">//左边</span></span>
Row(){
Row(){
Text(z.toString()).fontWeight(<span class="hljs-number"><span class="hljs-number">600</span></span>)
.fontColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-string"><span class="hljs-string">'#fff6f6e8'</span></span> : <span class="hljs-string"><span class="hljs-string">'#ff888888'</span></span>)
}
.justifyContent(FlexAlign.Center)
.width(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)
.backgroundColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色<span class="hljs-number"><span class="hljs-number">2</span></span> : <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色)
.brightness(<span class="hljs-number"><span class="hljs-number">0.8</span></span>)
.transform(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jz矩阵左平倾斜.copy())
.onClick(()=>{<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dj点击盒子(z)})
<span class="hljs-comment"><span class="hljs-comment">// .onTouch((e)=>{e.stopPropagation})</span></span>
<span class="hljs-comment"><span class="hljs-comment">// .border({width:1,color: '#fffaffff' })</span></span>
}
.translate({x:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,y:-(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)/<span class="hljs-number"><span class="hljs-number">2</span></span>})
.rotate({ z: <span class="hljs-number"><span class="hljs-number">1</span></span>, angle: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>,centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,centerY:<span class="hljs-number"><span class="hljs-number">0</span></span> })
<span class="hljs-comment"><span class="hljs-comment">//右边</span></span>
Row(){
Row(){
Text(z.toString()).fontColor(<span class="hljs-string"><span class="hljs-string">'#fff6f6e8'</span></span>).fontWeight(<span class="hljs-number"><span class="hljs-number">600</span></span>).margin({left:<span class="hljs-number"><span class="hljs-number">10</span></span>})
}
.width(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.yk右宽).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)
.backgroundColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色<span class="hljs-number"><span class="hljs-number">2</span></span> : <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色)
.brightness(<span class="hljs-number"><span class="hljs-number">1</span></span>)
.transform(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jz矩阵右平倾斜.copy())
.onClick(()=>{<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dj点击盒子(z)})
<span class="hljs-comment"><span class="hljs-comment">// .onTouch((e)=>{e.stopPropagation})</span></span>
<span class="hljs-comment"><span class="hljs-comment">// .border({width:1,color:'#fffaffff'})</span></span>
}
.translate({x:-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,y:-(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)/<span class="hljs-number"><span class="hljs-number">2</span></span>})
.rotate({ z: <span class="hljs-number"><span class="hljs-number">1</span></span>, angle: -<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>,centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,centerY:<span class="hljs-number"><span class="hljs-number">0</span></span> })
}<span class="hljs-comment"><span class="hljs-comment">//.zIndex(2)//.border({ width: 1, color: '#ff14ff03' })</span></span>
}.alignContent(Alignment.Start).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边+<span class="hljs-number"><span class="hljs-number">1</span></span>)
.zIndex(z)<span class="hljs-comment"><span class="hljs-comment">//.border({width:1,color: '#ffde0974' })</span></span>
.translate({
x:z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? -<span class="hljs-number"><span class="hljs-number">30</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
y:z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-number"><span class="hljs-number">30</span></span>*<span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.tan(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>*<span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.PI/<span class="hljs-number"><span class="hljs-number">180</span></span>) : <span class="hljs-number"><span class="hljs-number">0</span></span>
})
}
@State zk展开:boolean=false
@Builder hz盒子展开(z?:number){
Stack(){
//上盖
Row(){
Row().width(this.yk右宽).height(this.dg顶高)
.backgroundColor(z==this.dq当前 ? this.bj背景色 : this.bj背景色2)
.brightness(1.2)
.transform(this.zk展开 ? this.jz高 : matrix4.identity())
// .onClick(()=>{this.dj点击盒子(z)})
// .onTouch((e)=>{e.stopPropagation})
.border({width:1,color: ‘#fffaffff’ })
}//.zIndex(0)
.rotate({z:<span class="hljs-number"><span class="hljs-number">1</span></span>,
angle:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>+<span class="hljs-number"><span class="hljs-number">0.09</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移顶<span class="hljs-number"><span class="hljs-number">1</span></span>, centerY:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dg顶高
})
.translate({
x:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽 - <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移顶<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
y:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>
})
<span class="hljs-comment"><span class="hljs-comment">//左右</span></span>
Row() {
<span class="hljs-comment"><span class="hljs-comment">//左边</span></span>
Row(){
Row().width(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)
.backgroundColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色 : <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色<span class="hljs-number"><span class="hljs-number">2</span></span>)
.brightness(<span class="hljs-number"><span class="hljs-number">0.8</span></span>)
.transform(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jz矩阵左平倾斜.copy() : matrix4.identity())
<span class="hljs-comment"><span class="hljs-comment">// .onClick(()=>{this.dj点击盒子(z)})</span></span>
<span class="hljs-comment"><span class="hljs-comment">// .onTouch((e)=>{e.stopPropagation})</span></span>
.border({width:<span class="hljs-number"><span class="hljs-number">1</span></span>,color: <span class="hljs-string"><span class="hljs-string">'#fffaffff'</span></span> })
}
.rotate({ z: <span class="hljs-number"><span class="hljs-number">1</span></span>,
angle: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk左宽-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,centerY:<span class="hljs-number"><span class="hljs-number">0</span></span>
})
.translate({
x:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
y:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)/<span class="hljs-number"><span class="hljs-number">2</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>
})
<span class="hljs-comment"><span class="hljs-comment">//右边</span></span>
Row(){
Row(){
<span class="hljs-comment"><span class="hljs-comment">// Text(z.toString()).fontColor('#fff6f6e8').fontWeight(600).margin({left:10})</span></span>
}
.width(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.yk右宽).height(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)
.backgroundColor(z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色 : <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.bj背景色<span class="hljs-number"><span class="hljs-number">2</span></span>)
.brightness(<span class="hljs-number"><span class="hljs-number">1</span></span>)
.transform(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jz矩阵右平倾斜 : matrix4.identity())
<span class="hljs-comment"><span class="hljs-comment">// .onClick(()=>{this.dj点击盒子(z)})</span></span>
<span class="hljs-comment"><span class="hljs-comment">// .onTouch((e)=>{e.stopPropagation})</span></span>
.border({width:<span class="hljs-number"><span class="hljs-number">1</span></span>,color:<span class="hljs-string"><span class="hljs-string">'#fffaffff'</span></span>})
}
.rotate({ z: <span class="hljs-number"><span class="hljs-number">1</span></span>,
angle: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
centerX:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span>,centerY:<span class="hljs-number"><span class="hljs-number">0</span></span>
})
.translate({
x:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.py平移<span class="hljs-number"><span class="hljs-number">1</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
y:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.zk展开 ? -(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.xb斜边-<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.g高)/<span class="hljs-number"><span class="hljs-number">2</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>
})
}<span class="hljs-comment"><span class="hljs-comment">//.zIndex(2)//.border({ width: 1, color: '#ff14ff03' })</span></span>
}.alignContent(Alignment.Start).height(<span class="hljs-number"><span class="hljs-number">60</span></span>)<span class="hljs-comment"><span class="hljs-comment">//.height(this.xb斜边+1)</span></span>
.zIndex(z)<span class="hljs-comment"><span class="hljs-comment">//.border({width:1,color: '#ffde0974' })</span></span>
.translate({
x:z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? -<span class="hljs-number"><span class="hljs-number">30</span></span> : <span class="hljs-number"><span class="hljs-number">0</span></span>,
y:z==<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dq当前 ? <span class="hljs-number"><span class="hljs-number">30</span></span>*<span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.tan(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.jd角度<span class="hljs-number"><span class="hljs-number">1</span></span>*<span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.PI/<span class="hljs-number"><span class="hljs-number">180</span></span>) : <span class="hljs-number"><span class="hljs-number">0</span></span>
})
}
hzzk盒子展开(){
animateTo({
duration:2000,curve:Curve.EaseInOut
},()=>{
this.zk展开=!this.zk展开
})
}
dj点击盒子(z:number){
animateTo({
duration:1000,curve:curves.springMotion(0.45,0.35)
},()=>{
if (z==this.dq当前){
this.dq当前=0
}else{
this.dq当前=z
}
})
}
build() {
Column({ space: 10 }) {
Column() {
this.hz盒子(14)
this.hz盒子(13)
this.hz盒子(12)
this.hz盒子(11)
this.hz盒子(10)
Blank(<span class="hljs-number"><span class="hljs-number">100</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.hz盒子展开()
Button(<span class="hljs-string"><span class="hljs-string">'盒子组成'</span></span>).fontColor(<span class="hljs-string"><span class="hljs-string">'#ffd8edf3'</span></span>).height(<span class="hljs-number"><span class="hljs-number">30</span></span>).margin({top:<span class="hljs-number"><span class="hljs-number">10</span></span>}).onClick(()=><span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.hzzk盒子展开())
}
Column({space:<span class="hljs-number"><span class="hljs-number">1</span></span>}){
<span class="hljs-comment"><span class="hljs-comment">// Text('当前点击: ' + this.dq当前 + ' ' + this.cc抽出).fontColor('#ffe6e8ea')</span></span>
<span class="hljs-comment"><span class="hljs-comment">// Text('高: ' + this.g高.toFixed(0)).fontColor('#ffe6e8ea')</span></span>
<span class="hljs-comment"><span class="hljs-comment">// Text('平移: ' + this.py平移1.toFixed(0)).fontColor('#ffe6e8ea')</span></span>
<span class="hljs-comment"><span class="hljs-comment">// Text('左宽: ' + this.zk左宽.toFixed(0)).fontColor('#ffe6e8ea')</span></span>
<span class="hljs-comment"><span class="hljs-comment">// Text('顶高: ' + this.dg顶高.toFixed(0)).fontColor('#ffe6e8ea')</span></span>
<span class="hljs-comment"><span class="hljs-comment">// Text('顶高平移: ' + this.py平移顶1.toFixed(0)).fontColor('#ffe6e8ea')</span></span>
}
}.ymys页面样式()
}
}
@Extend(Column) function ymys页面样式(){
.width(‘100%’)
.height(‘100%’)
.backgroundColor(’#ff161616’)
.justifyContent(FlexAlign.Center)
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
关于HarmonyOS 鸿蒙Next Matrix4倾斜变换,立体盒子动画,API 9的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
HarmonyOS的流畅度和稳定性都让我非常满意,值得推荐给大家。