近期遇到了一个六边形边框的需求,实现如下图效果:有六边形边框,中间是一张图片,图片超出的部分要裁切掉。
代码实现如下:
<html>
<head>
<style>
html,body{
width:100%;
height:100%;
padding:0;
margin:0;
}
canvas{
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
margin:auto;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext("2d");
//六边形横向宽
width = 209;
//边框粗细
borderWidth = 3;
//六边形边长
hexagonWidth = (width - borderWidth)/4;
//设置canvas宽高
canvas.width = width;
canvas.height = width / 2 * Math.sqrt(3) + borderWidth;
//图片缩放比例
imgScale = 0.5;
//绘制图片
var img = new Image()
img.src = './1.png'
img.onload = function(){
context.drawImage(this, canvas.width/2 - img.width/2*imgScale , canvas.height/2 - img.height/2*imgScale , img.width*imgScale , img.height*imgScale)
//如果图片绘制后覆盖边框,可再次调用一边绘制六边形代码
}
//绘制六边形,裁切
context.beginPath();
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.strokeStyle = '#79b1f7';
context.lineWidth = borderWidth;
context.lineTo(-1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.lineTo(1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.lineTo(2*hexagonWidth,0*hexagonWidth);
context.lineTo(1*hexagonWidth,-1 * Math.sqrt(3)*hexagonWidth);
context.lineTo(-1*hexagonWidth,-1 * Math.sqrt(3)*hexagonWidth);
context.lineTo(-2*hexagonWidth,0*hexagonWidth);
context.lineTo(-1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.stroke();
context.restore();
context.clip();
context.closePath();
</script>
</html>
如果图片太大时会出现覆盖边框的问题,如下图。这是由于canvas绘制线条的特性而导致的(以中心向两边绘制固定宽度,比如代码中设置的宽度为3,则连接线外部与内部的宽度各为1.5,所以覆盖的边框宽为1.5)。
解决代码如下:
//图片缩放比例
imgScale = 1;
img.onload = function(){
context.drawImage(this, canvas.width/2 - img.width/2*imgScale , canvas.height/2 - img.height/2*imgScale , img.width*imgScale , img.height*imgScale)
//如果图片绘制后覆盖边框,可再次调用一边绘制六边形代码
context.beginPath();
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.strokeStyle = '#79b1f7';
context.lineWidth = borderWidth;
context.lineTo(-1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.lineTo(1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.lineTo(2*hexagonWidth,0*hexagonWidth);
context.lineTo(1*hexagonWidth,-1 * Math.sqrt(3)*hexagonWidth);
context.lineTo(-1*hexagonWidth,-1 * Math.sqrt(3)*hexagonWidth);
context.lineTo(-2*hexagonWidth,0*hexagonWidth);
context.lineTo(-1*hexagonWidth,Math.sqrt(3)*hexagonWidth);
context.stroke();
context.restore();
context.closePath();
}
解决后效果图如下: