Last active
April 24, 2016 13:20
-
-
Save jinzhan/31458be6c083ea3cd8f6 to your computer and use it in GitHub Desktop.
a js to make a hexagon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @description: 灵感来自于:http://www.colorhexa.com/ | |
* 该网站的logo是用svg生成,http://www.colorhexa.com/static/i/logo.min.svg | |
* 这里我想使用js生成一个正六边形,基本思路: | |
* 1.这个正六边形的边,恰好是由30个等边三角形构成; | |
* 2.假设三角形的边长为n;则六边形的高度为:n*6,宽度为n*sin60*6 | |
* 3.整体用百分比,以便自适应宽度 | |
* @author: jinzhan | |
* @email: steinitz@qq.com | |
* **/ | |
// 三角形边长,假设为1个单位 | |
var TRIANGLE_SIDE_LENGTH = 1; | |
// 三角形高度 | |
var TRIANGLE_HEIGHT = Math.sin(60 * Math.PI / 180) * TRIANGLE_SIDE_LENGTH; | |
// 水平的偏移,以保持多边形居中展示 | |
var HORIZONTAL_OFFSET = (TRIANGLE_SIDE_LENGTH - TRIANGLE_HEIGHT) * 6 / 2; | |
// 百分比转化比例 | |
var RATIO = 100 / 6; | |
// 累计30个三角形,可以看作是2个三角形的translate得到的(当然,也可以是1个三角形经过translate,scale或rotate也能得到) | |
var TRIANGLE_NUM = 30; | |
// 以顶点在左上角的两个三角形为基准,3个顶点的位置: | |
// [ | |
// P1.x, P1.y, | |
// P2.x, P2.y, | |
// P3.x, P3.y | |
// ] | |
var BASIC_RIGHT_WARD_TRIANGLE_POINT = [ | |
HORIZONTAL_OFFSET, TRIANGLE_SIDE_LENGTH * 1.5, | |
HORIZONTAL_OFFSET, TRIANGLE_SIDE_LENGTH * 2.5, | |
HORIZONTAL_OFFSET + TRIANGLE_HEIGHT, TRIANGLE_SIDE_LENGTH * 2 | |
]; | |
var BASIC_LEFT_WARD_TRIANGLE_POINT = [ | |
HORIZONTAL_OFFSET, TRIANGLE_SIDE_LENGTH * 1.5, | |
HORIZONTAL_OFFSET + TRIANGLE_HEIGHT, TRIANGLE_SIDE_LENGTH, | |
HORIZONTAL_OFFSET + TRIANGLE_HEIGHT, TRIANGLE_SIDE_LENGTH * 2 | |
]; | |
var PALLET = [ | |
'#22B0B1', | |
'#26B1C9', | |
'#5ABFD6', | |
'#7DD0F0', | |
'#AADEF7', | |
'#7EB5D2', | |
'#397599', | |
'#145079', | |
'#22406A', | |
'#2E2146', | |
'#4D1B50', | |
'#5E0F45', | |
'#7F205B', | |
'#A03271', | |
'#C23252', | |
'#D63140', | |
'#D63140', | |
'#EA312F', | |
'#EB4C2F', | |
'#ED752F', | |
'#F49A2E', | |
'#F9B62F', | |
'#FEC931', | |
'#D5CB36', | |
'#ACCE42', | |
'#76C347', | |
'#48B74B', | |
'#22AC51', | |
'#22AE67', | |
'#22AF94' | |
]; | |
// 随机获得一个颜色 | |
var getRandomColor = function () { | |
return '#' + ('00000' + ((Math.random() * (Math.pow(16, 6) - 1)) ^ 0).toString(16)).substr(-6); | |
}; | |
/* | |
* @param {string|HTMLElement} container 生成的hexagon所在容器 | |
* @param {object} option | |
* */ | |
var Hexagon = function (container, option) { | |
// 放置的容器 | |
this.$container = $(container); | |
this.option = $.extend({ | |
pallet: PALLET, | |
width: 500, | |
height: 500, | |
transitionDuration: 0.3 //0.3s | |
}, option); | |
// 添加正六边形外层容器 | |
this.$el = $('<div></div>').css({ | |
width: this.option.width, | |
height: this.option.height, | |
position: 'relative' | |
}); | |
this.$container.append(this.$el); | |
this.init(); | |
}; | |
Hexagon.prototype = { | |
init: function () { | |
this.createAngle(); | |
setTimeout($.proxy(this.updatePoints, this), 1000); | |
}, | |
createAngle: function () { | |
// 构造三角形容器 | |
for (var i = 0; i < TRIANGLE_NUM; i++) { | |
var $$el = $('<div></div>') | |
.attr('id', 'triangle-n-' + i).css({ | |
position: 'absolute', | |
width: '100%', | |
height: '100%', | |
transition: 'all ' + this.option.transitionDuration + 's', | |
// transform: 'translate(' + (TRIANGLE_HEIGHT * 2.5 * RATIO) + '%,' + (TRIANGLE_SIDE_LENGTH * RATIO) + '%)' | |
// background: randomColor() | |
background: this.option.pallet[i] | |
}); | |
var middle = TRIANGLE_SIDE_LENGTH * 6 / 2; | |
// 起始点为中心 | |
$(this.$el).append(this.setClipPath($$el, [ | |
middle, middle, middle, middle, middle, middle | |
])); | |
} | |
}, | |
updatePoints: function () { | |
// 使用clip-path数据来偏移 | |
var right_ward_points = this.getAnglePoints(BASIC_RIGHT_WARD_TRIANGLE_POINT, !0); | |
var left_ward_points = this.getAnglePoints(BASIC_LEFT_WARD_TRIANGLE_POINT, 0); | |
var points = right_ward_points; | |
var i = 1; | |
var item; | |
while (item = left_ward_points.shift()) { | |
points.splice(i, 0, item); | |
i = i + 2; | |
} | |
var $div = this.$el.children('div'); | |
var me = this; | |
for (var m = 0, l = points.length; m < l; m++) { | |
// setClipPath | |
void function (m) { | |
setTimeout(function () { | |
me.setClipPath($div.eq(m), points[m]); | |
}, 50 * m); | |
}(m); | |
} | |
}, | |
// 得到三角形的偏移数据坐标 | |
getAnglePoints: function (basicPoint, isRightwards) { | |
var points = []; | |
var t; | |
// 按照三角形箭头方向分左右 | |
isRightwards = !!isRightwards; | |
points.push(basicPoint); | |
for (var i = 1; i < TRIANGLE_NUM / 2; i++) { | |
// 将基准坐标的数组copy一份 | |
t = points[i - 1].concat(); | |
switch (!0) { | |
// 顺时针的第1边 | |
case i < 3 || (i === 3 && isRightwards): | |
// 横坐标的位移为:TRIANGLE_HEIGHT | |
// 纵坐标的位移为:-TRIANGLE_SIDE_LENGTH/2 | |
// 即: | |
t[0] += TRIANGLE_HEIGHT; | |
t[1] -= TRIANGLE_SIDE_LENGTH / 2; | |
t[2] += TRIANGLE_HEIGHT; | |
t[3] -= TRIANGLE_SIDE_LENGTH / 2; | |
t[4] += TRIANGLE_HEIGHT; | |
t[5] -= TRIANGLE_SIDE_LENGTH / 2; | |
break; | |
// 第2边 | |
case i < 6: | |
t[0] += TRIANGLE_HEIGHT; | |
t[1] += TRIANGLE_SIDE_LENGTH / 2; | |
t[2] += TRIANGLE_HEIGHT; | |
t[3] += TRIANGLE_SIDE_LENGTH / 2; | |
t[4] += TRIANGLE_HEIGHT; | |
t[5] += TRIANGLE_SIDE_LENGTH / 2; | |
break; | |
// 第3边 | |
case i < 8 || (i === 8 && isRightwards): | |
// 纵坐标的位移为:TRIANGLE_SIDE_LENGTH | |
t[1] += TRIANGLE_SIDE_LENGTH; | |
t[3] += TRIANGLE_SIDE_LENGTH; | |
t[5] += TRIANGLE_SIDE_LENGTH; | |
break; | |
// 第4边 | |
case i < 11: | |
t[0] -= TRIANGLE_HEIGHT; | |
t[1] += TRIANGLE_SIDE_LENGTH / 2; | |
t[2] -= TRIANGLE_HEIGHT; | |
t[3] += TRIANGLE_SIDE_LENGTH / 2; | |
t[4] -= TRIANGLE_HEIGHT; | |
t[5] += TRIANGLE_SIDE_LENGTH / 2; | |
break; | |
// 第5边 | |
case i < 13 || (i === 13 && isRightwards): | |
t[0] -= TRIANGLE_HEIGHT; | |
t[1] -= TRIANGLE_SIDE_LENGTH / 2; | |
t[2] -= TRIANGLE_HEIGHT; | |
t[3] -= TRIANGLE_SIDE_LENGTH / 2; | |
t[4] -= TRIANGLE_HEIGHT; | |
t[5] -= TRIANGLE_SIDE_LENGTH / 2; | |
break; | |
// 第6边 | |
case i < 15: | |
t[1] -= TRIANGLE_SIDE_LENGTH; | |
t[3] -= TRIANGLE_SIDE_LENGTH; | |
t[5] -= TRIANGLE_SIDE_LENGTH; | |
} | |
points.push(t); | |
} | |
return points; | |
}, | |
setClipPath: function (el, data) { | |
var polygon = ''; | |
$.each(data, function (index, item) { | |
if (index) { | |
polygon += index % 2 ? ' ' : ','; | |
} | |
// 将位置转化为百分比 | |
polygon += item * RATIO + '%'; | |
}); | |
return $(el).css({ | |
'-webkit-clip-path': 'polygon(' + polygon + ')' | |
}); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment