内容简介:这次项目用到了一些自定义的数据可视化组件,我把我做的部分抽出来几个典型做个汇总。分为如下:有些图片(例如下面这个jpg动图)太大,进行了一定程度的压缩,有点模糊(^_^)。
前言:
这次项目用到了一些自定义的数据可视化组件,我把我做的部分抽出来几个典型做个汇总。
分为如下:
- 星球环绕旋转图 -- 方法一: svg:animateMotion+ animateTransform 方法二:css3d
- 地图 -- svg渲染 + div悬浮框 + js事件
- 二维饼图(风车图) -- canvas: dragCircle 、 stopDragging
- 三棱锥 -- canvas + 对数排列
- 长方体 -- css3d + 增量增长
星球环绕旋转图
效果展示:
有些图片(例如下面这个jpg动图)太大,进行了一定程度的压缩,有点模糊(^_^)。
我的碎碎念(*^3^):
步骤:
方法一:svg的animateMotion属性 + animateTransform属性
//举例一个星球的动画 <animateMotion dur="6s" begin="0" repeatCount="indefinite"> <mpath xlinkHref="#Path-12" /> //轨迹动画 </animateMotion> <animateTransform //自身动画,靠近我的时候星球变大,远离我时变小 id="first" attributeType="XML" attributeName="transform" type="scale" begin="0;second.end " from="1" to="0.512" dur="3s" fill="freeze" /> <animateTransform id="second" attributeType="XML" attributeName="transform" type="scale" begin="first.end" from="0.512" to="1" dur="3s" fill="freeze" />复制代码
方法二:css3d
参考链接: www.jianshu.com/p/2b85973ad…
- html:
<!-- 轨道 -->
<div class="orbit">
<!-- 行星 -->
<div class="planet planet1">
<!-- <span class="name"></span> -->
</div>
<div class="planet planet2">
<!-- <span class="name"></span> -->
</div>
</div>复制代码
- css:
.orbit { //轨道旋转,公转
border: 5px solid red;
transform-style: preserve-3d;
padding: 65px;
width: 500px;
height: 500px;
border-radius: 50%;
animation: orbit-rotate 10s linear infinite;
}
.planet { //星球自转
width: 50px;
height: 50px;
background: url('../../img/ball1.png') no-repeat;
background-size: 100% 100%;
border-radius: 50%;
animation: self-rotate 10s linear infinite;
}
// (1)rotateX 是为了让整个面倾斜,translateZ是为了防止椭圆(border)因为倾斜发生锯齿,
// (2)停顿效果的产生,其实我是走了野路子的。五个球,根据360/5=72,写了五个不同的关于orbit的class,
// 0 + 72,....360依次增加72,直到360,利用setimeout每隔4秒,按顺序切换一个class
@keyframes orbit-rotate {
0% {
transform: rotateX(70deg) rotateZ(0deg) translateZ(0);
}
100% {
transform: rotateX(70deg) rotateZ(-360deg) translateZ(0);
}
}
@keyframes self-rotate {
0% {
transform: rotateX(-90deg) rotateY(360deg) rotateZ(0deg);
}
100% {
transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg);
}
}
.planet1 { //确定星球开始位置
position: absolute;
top: 65px;
right: 65px;
}
.planet2 { //确定星球开始位置
position: absolute;
bottom: 65px;
right: 65px;
}
复制代码
==/**注意 **/==
参考链接: zh.wikipedia.org/wiki/%E6%A4…
如果为了让星球排列五等分,并且大小根据数值改变星球大小,可以采用以下公式:中心位于点 (h,k)的主轴平行于 x 轴的椭圆由如下方程指定,改变top,left值
♪───O(≧∇≦)O────♪可爱的分割线♪───O(≧∇≦)O────♪
地图
效果展示:
我的碎碎念(*^3^):
步骤:
- 文件内容
地图文件如下:index.js主文件包含悬浮事件,index.less样式文件,mapStyle.js存放背景地图,pathStyle.js数组格式存放代表地图上小块的路径
- 渲染地图
代码如下:
根据接口给的数据,按照五个色系分别给不同的path填充(fill)不同的颜色
const colorMap = [
'rgba(89, 126, 247, 0.8)',
'rgba(0, 121, 254, 0.8)',
'rgba(0, 121, 254, 0.8)',
'rgba(38, 168, 254, 0.8)',
'rgba(192, 228, 253, 0.8)',
];复制代码
- 增加悬浮事件
render代码如下:
鼠标移入事件:
鼠标移出事件:
♪───O(≧∇≦)O────♪可爱的分割线♪───O(≧∇≦)O────♪
二维饼图(风车图)
效果展示:
我的碎碎念(*^3^):
步骤:
- 传入参数
option.push=[{
color: color[i], //饼图块颜色
radius: item.revenueTaxAvg, //饼图块半径
name: item.domainName, // 饼图块名称
angle: item.companyCnt, //饼图块角度
}];复制代码
- 画饼图,PieCanvas.drawPieCanvas('econComposChart', option);
怎么画饼图?,可以参考我以前写的一篇文章: juejin.im/post/5b1e27…
==/* 注意 */==
这篇文章画的是angle一个纬度,只要再增加另外一个纬度radius就好。
canvas画的文字和图,会有一定程度的模糊,解决方案:把画布的宽高增加2倍。
- 悬浮事件
进行碰撞检测,判断鼠标悬浮是落在哪个弧度的饼图块之间,如果不再饼图块里面悬浮样式消失。
数学里主要判断逻辑如下:
if(点到圆心的距离<圆的最大半径
&&点到圆心的距离>圆的最小半径
&&点到圆心的直线的角度>扇形的起始角度
&&点到圆心的直线的角度<扇形的结束角度){
点在扇形区域内
}
//使用勾股定理计算这个点与圆心之间的距离 distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)) //α(弧度)= L (弧长)/ r(半径),但是弧长,我求不出来。 (点到圆心的直线的角度)的范围我主要使用sin(x),如下方法。 判断不同区间的sin(x)值大小,推断出悬浮区域所在的值是什么。复制代码
♪───O(≧∇≦)O────♪可爱的分割线♪───O(≧∇≦)O────♪
三棱锥
效果展示:
步骤:
主要原理:两个三角形 + 一个园 = 三棱锥
canvas.width = canvas.offsetWidth; //防止图片变形
canvas.height = canvas.offsetHeight;
ctx.clearRect(0, 0, canvas.width, canvas.height); 清除画布
const { height } = canvas; // 计算等边三角形的高
//如下图,第一个三角形 A-B-C
ctx.moveTo(100, 0); // 从A(100,0)开始
ctx.lineTo(0, height); // 从A(100,0)开始,画到B (0,height)结束
ctx.lineTo(144, height); // B(0,height)-C(144, height)
//第二个三角形 A-C-D
ctx.moveTo(100, 0); // 从A(100,0)开始
ctx.lineTo(143, height); // A-C
ctx.lineTo(210, height); // C-D
//第三个画圆
ctx.arc(100, 23 , 23, 0, Math.PI * 2, false); // 画圆
<canvas id={`pyramid${id}`} height={itemHeight} /> //计算itemHeight复制代码
对数增长--三棱锥高度(itemHeight)计算:
假设输入
data = [0, 1, 2, 3, 4, 5],x为其中任意值;
maxHeight 为最大高度;
输出
itemHeight(0 <= itemHeight< maxHeight),成对数增长
//求最大值
const max = MAX(data)
//排除 x === 0 的情况
因为logmax(max)= 1,且x > 0
由上图可得 0 < logmax(x)< 1
所以 0 < logmax(x) * maxHeight < maxHeight
可知 logmax(x) * maxHeight 成对数变化
又因为logmax(x) = loge(x) / loge(max)
//写成代码为
const max =data((a, b) => {
return a > b ? a : b;
}, 0);
itemHeight = x===0 ? 0 : Math.log(x) / Math.log(max) * maxHeight
复制代码
==/* 注意 */==
y轴计算采用指数增长,因为任意max的0次方 = 1, 所以单独判断 i <= 0的情况
i > 0 ? Math.round(max ** (i * 0.25)) : 0
长方体
效果展示:
步骤:
html
<div id="cube">
<figure class="front">1</figure>
<figure class="back">2</figure>
<figure class="right">3</figure>
<figure class="left">4</figure>
<figure class="top">5</figure>
<figure class="bottom">6</figure>
</div>复制代码
css
#box.show-front { transform: translateZ( -50px ) rotateY( 0deg ); }
#box.show-back { transform: translateZ( -50px ) rotateX( -180deg ); }
#box.show-right { transform: translateZ( -150px ) rotateY( -90deg ); }
#box.show-left { transform: translateZ( -150px ) rotateY( 90deg ); }
#box.show-top { transform: translateZ( -100px ) rotateX( -90deg ); }
#box.show-bottom { transform: translateZ( -100px ) rotateX( 90deg ); } 复制代码
♪───O(≧∇≦)O────♪可爱的分割线♪───O(≧∇≦)O────♪
总结
我第一次写这么多字的总结技术的文章,排版有点乱,(╯°□°)╯︵ ┻━┻。大部分的内容其实很简单,用到的基本上是初中、高中里面最基础的数学(其实难了,我也不会了_φ(・_・)。
厚着脸皮说,我可能文字功底不咋地,但是每个例子的中心思想应该都表达了。
最后的最后,看在我第一次写了这么多字的份上,给个赞呗(///▽///)。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP and MySQL Web Development
Luke Welling、Laura Thomson / Sams / July 25, 2007 / $49.99
Book Description PHP and MySQL Web Development teaches you to develop dynamic, secure, commerical Web sites. Using the same accessible, popular teaching style of the three previous editions, this b......一起来看看 《PHP and MySQL Web Development》 这本书的介绍吧!