FUI设计语言之电子流光动效

DEMO收录在 春·重返创世 中,这是附上时光机链接: BrokenLine。您可通过刷新页面,随机渲染不同的线路造型。这篇文章在实现层面将分为两个部分,一是流光沿着折线/直线运动的实现思路,二是如何自动生成随机45度转角单线路。

THREE.js中的Curve实现了可以获取路径上每一点的位置的基类。

.getPoint ( t : Float, optionalTarget : Vector ) : Vector
.getPointAt ( u : Float, optionalTarget : Vector ) : Vector
.getPoints ( divisions : Integer ) : Array
.getSpacedPoints ( divisions : Integer ) : Array

由于电路中不存在曲线,所以这里我使用自己的方法实现获取路径上的位置。

运动的流光需要确定首尾两个点的位置,这两个沿路经一前一后移动就形成了流光的动效。把电子流动的线当作对象,那么对象中应当包含每一个拐点的位置信息以及流光当前的位置。

[
  [0, 0],
  [0, 100],
  [100, 200],
  [100, 300]
]

上方代码片段表示四个节点(包含起始、终止位置),将这些数据作为输入数据,进入内部处理。

from: {
  x: points[ i ][ 0 ],
  y: points[ i ][ 1 ],
}

to: {
  x: points[ i+1 ][ 0 ],
  y: points[ i+1 ][ 1 ],
}

将输入数据解析为为电子流对象的节点属性。

_linear_gradient = this.ctx.createLinearGradient(this.eP.x, this.eP.y, this.sP.x, this.sP.y);
_linear_gradient.addColorStop(0, 'hsla('+ this.lightColorH +', '+ this.lightColorS +'%, '+ this.lightColorL +'%, 0)');
_linear_gradient.addColorStop(0.95, 'hsla('+ this.lightColorH +', '+ this.lightColorS +'%, '+ this.lightColorL +'%, 1)');
_linear_gradient.addColorStop(1, 'hsla('+ this.lightColorH +', '+ this.lightColorS +'%, '+ this.lightColorL +'%, 0)');

不断调整电流前后两端点位置,使用canvas绘图上下文提供的创建线性渐变上下文创建线性渐变对象,并设置前后端点的颜色值。

this.start_point_offset += this.point_speed;
this.sP = {
	x: this.parsedPoint[this.startSlopeIndex].from.x + Math.round(this.start_point_offset * Math.cos(this.parsedPoint[this.startSlopeIndex].slope) ) ,
	y: this.parsedPoint[this.startSlopeIndex].from.y + Math.round(this.start_point_offset * Math.sin(this.parsedPoint[this.startSlopeIndex].slope) ),
};
var _start_go_more;
if(this.parsedPoint[this.startSlopeIndex+1]){
	_start_go_more = 0;
}else{
	_start_go_more = this.step_length;
}
if(this.start_point_offset >= (this.parsedPoint[this.startSlopeIndex].length + _start_go_more)){
	this.startSlopeIndex ++;
	this.start_point_offset = 0;
	if(this.startSlopeIndex >= this.parsedPoint.length){
		this.startSlopeIndex = 0;
		this.start_point_offset = 0;
	}
}
this.end_point_offset += this.point_speed;
this.eP = {
	x: this.parsedPoint[this.endSlopeIndex].from.x + Math.round(this.end_point_offset * Math.cos(this.parsedPoint[this.endSlopeIndex].slope) ) ,
	y: this.parsedPoint[this.endSlopeIndex].from.y + Math.round(this.end_point_offset * Math.sin(this.parsedPoint[this.endSlopeIndex].slope) ),
};
if(this.end_point_offset >= (this.parsedPoint[this.endSlopeIndex].length)){
	this.endSlopeIndex ++;
	this.end_point_offset = 0;
	if(this.endSlopeIndex >= this.parsedPoint.length){
		this.endSlopeIndex = 0;
		this.end_point_offset = - this.step_length;
	}
}

上方为核心代码,电子流的折线被分解为多条线段,线段转换为函数方程式,如此便可以随着点落在x轴上的值得到点落在y轴上的值,这样就能得到点的位置。当这一过程不断重复,就能得到不断变化的点的位置信息。

当然还需要定义电子流一前一后的距离,以及电子流的流速。

function createRandomBrock(beginX, beginY, xyChangeLength, maxYChangeLength){

	var stepNumber = 3 + parseInt(Math.random() * 2);
	var points = [];
	var _x = beginX;
	var _y = beginY;
	points.push([_x, _y]);
	var _xsRandom;
	var _xs;
	var changeHistory = [];
	var needChange;
	var changeLength = xyChangeLength;
	var stepLength;
	for(var i=0; i<stepNumber; i++){
		stepLength = 100 + Math.random() * 130;
		if(stepLength > maxYChangeLength){
			stepLength = maxYChangeLength;
		}

		if(changeHistory.length == 0){
			needChange = parseInt(Math.random()*2);

			if(needChange == 1){
				_xsRandom = parseInt(Math.random()*2);
				if(_xsRandom){
					_xs = 1;
				}else{
					_xs = -1;
				}
				_x += _xs*changeLength;
				_y += changeLength;
			}else{
				_y += stepLength;
			}

			points.push([_x, _y]);

			changeHistory.push(needChange);
			continue;
		}
		if(changeHistory[changeHistory.length-1] == 0){

			needChange = parseInt(Math.random()*2);

			if(needChange == 1){
				_xsRandom = parseInt(Math.random()*2);
				if(_xsRandom){
					_xs = 1;
				}else{
					_xs = -1;
				}
				_x += _xs*changeLength;
				_y += changeLength;
			}else{
				_y += stepLength;
			}

			points.push([_x, _y]);

			changeHistory.push(needChange);
			continue;
		}else if(changeHistory[changeHistory.length-1] == 1){
			needChange = 0;
			_y += stepLength;
			points.push([_x, _y]);
			changeHistory.push(needChange);
			continue;
		}
	}
	brokenManager.push(new fcharts.BrokenLine({
		ctx: context,
		points: points,
		point_speed: 1,
		step_length: 90,
		lightWidth: 2,
		lightBgStyle: 'hsla(182, 100%, 60%, 0.4)',
		lightColorH: 179,
		lightColorS: 100,
		lightColorL: 50,
	}));
}

定义方法自动创建45度拐角电子流。

文章标签:fui,futureUI

永久链接:http://www.shuaihua.cc/article/fiction-user-interface-for-electronic-effect

快速跳转:陈帅华 - 心头好文 - libraries - FUI设计语言之电子流光动效

fiction-user-interface-for-electronic-effect

发表日期:2018-7-14

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证