Skip to content

Instantly share code, notes, and snippets.

@jinzhan
Last active April 24, 2016 13:20
Show Gist options
  • Save jinzhan/31458be6c083ea3cd8f6 to your computer and use it in GitHub Desktop.
Save jinzhan/31458be6c083ea3cd8f6 to your computer and use it in GitHub Desktop.
a js to make a hexagon
/**
* @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