临近年末,项目也少了,闲来无事回顾了一下以前的项目,顺便也学习一下前端,作为一个后端开发人员,以前也写过一些jsp,现在前后端分离了,咱也来前端瞧瞧,凑凑热闹 O(∩_∩)O哈哈~。
回顾了一下以前的一个项目,有一个需求 显示一个电子报,点击电子报的某一个板块,显示该板块的详细内容,然而当时并没有采用canvas来绘制阴影,导致只能显示一些矩形的阴影 有些多边形的阴影并没有很好的显示出来,所以尝试了一下使用canvas来绘制我们图片热区 map_area 中的rect circle poly,尝试的结果如下
尽管前端知识有些缺乏,代码写的有些丑陋,我还是把它丢出来让大家来瞧瞧,希望大家多多指正,我好把它改一改。封装了一个vue
hotspot-shadow.vue
<template>
<div class="wrapper" style="position: relative">
<div>
<img
:src="imgUrl"
usemap="#netmap"
:alt="imgAlt"
:height="imgHeight + 'px'"
:width="imgWidth + 'px'"
ref="img"
/>
<map name="netmap" id="netmap">
<area
v-for="(area, index) in areas"
:key="index"
:shape="area.type"
:coords="area.coord"
:title="area.dhref"
alt=""
@mouseover="showShadow($event)"
/>
</map>
</div>
<div
style="
position: absolute;
top: 0;
left: 0;
display: none;
cursor: pointer;
"
id="shadowDiv"
>
<canvas
:width="canvasWidth"
:height="canvasHeight"
id="myCanvas"
@mouseout="hiddenDiv"
@mousemove="jugeInShadow($event)"
@click="openHref($event)"
>
您的浏览器不支持 HTML5 canvas 标签。
</canvas>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
/**
说明如下:
openType:热区连接内容打开方式,window.open() 中的name, 值可以是blank(新窗口打开) 或者 self(替换当前页面),其他值也没做限制
shadowColor: 阴影部分的颜色 默认为粉色 不透明度 0.5 当然你也可以改
imgUrl:热区图片的地址 本地图片传参需要加一个 require("./1.jpg")
imgAlt: 图片的文本替换内容
imgHeight:图片的高宽(注意这个值与 area 中的coord 值息息相关,如果变了则coord的值也要变)想做一个缩放参数的,由于没有时间就不做了
imgWeight:图片的高宽(注意这个值与 area 中的coord 值息息相关)
areas 是个数组 每个元素是一个对象格式如下
{
type:"rect" | "circle" | "poly"
coord:"100,100,200,200"
href:"www.baidu.com" //这里是一个链接 window.open 打开该链接
}
*/
openType: {
type: String,
default: "blank",
},
shadowColor: {
type: String,
default: "rgba(255,220,220,0.5)",
},
imgUrl: {
type: String,
default: "",
},
imgAlt: {
type: String,
default: "",
},
imgHeight: {
type: String,
default: 800,
},
imgWidth: {
type: String,
default: 550,
},
areas: {
type: Array,
default() {
return [];
},
},
},
created() {
if (this.imgWidth !== 550) {
this.widthRate = (this.imgWidth / 550).toFixed(2);
}
if (this.imgHeight !== 800) {
this.heightRate = (this.imgHeight / 800).toFixed(2);
}
this.areas.forEach((item) => {
if (item.type == "poly" || item.type == "rect") {
let coordinate = item.coord.split(",");
let coord = "";
for (let i = 0; i < coordinate.length; i++) {
if (i % 2 == 0) {
coordinate[i] *= this.widthRate;
} else {
coordinate[i] *= this.heightRate;
}
coord += coordinate[i] + ",";
}
coord = coord.substr(0, coord.length - 1);
item.coord = coord;
} else if (item.type == "circle") {
let coordinate = item.coord.split(",");
coordinate[0] *= this.widthRate;
coordinate[1] *= this.heightRate;
coordinate[2] *= this.widthRate;
item.coord = coordinate[0] + "," + coordinate[2] + "," + coordinate[2];
}
});
this.canvasWidth *= this.widthRate;
this.canvasHeight *= this.heightRate;
},
mounted() {
this.relativePosX = this.$refs.img.getBoundingClientRect().x;
this.relativePosY = this.$refs.img.getBoundingClientRect().y;
},
data() {
return {
relativePosX: 0,
relativePosY: 0,
heightRate: 1,
widthRate: 1,
// canvas画布的宽度
canvasWidth: 400,
// canvas画布的高度
canvasHeight: 200,
// 所在阴影的链接 每次移动到阴影上都会修改
shadowHref: "",
};
},
methods: {
hiddenDiv() {
// 移出 遮罩的div 则隐藏遮罩的div
let e = document.getElementById("shadowDiv");
e.style.display = "none";
},
openHref(event) {
// 在阴影中点击打开链接
let e = document.getElementById("shadowDiv");
let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
let xmin = e.style.left.replace("px", "");
let ymin = e.style.top.replace("px", "");
// 通过 canvas的isPointInPath 来判断点击的位置 是在绘制的图形上 而不只是在canvas的画布上
if (
ctx.isPointInPath(
event.pageX - this.relativePosX - xmin,
event.pageY - this.relativePosY - ymin
)
) {
//在则打开新链接
// 这里可以再 设置一个方法 通过父组件来操作,这里就不再多说
//window.open(this.shadowHref, "_" + this.openType);
let content = "";
this.$axios.get(this.shadowHref).then((res) => {
this.$emit("changeContent", res.data);
});
}
},
jugeInShadow(event) {
// 如果在canvas 的画布上移动,但是当你移除所绘制的图形(阴影) 则也判定离开
let e = document.getElementById("shadowDiv");
let xmin = e.style.left.replace("px", "");
let ymin = e.style.top.replace("px", "");
let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
// 通过 canvas的isPointInPath 来判断点击的位置 是在绘制的图形上 而不只是在canvas的画布上
if (
!ctx.isPointInPath(
event.pageX - this.relativePosX - xmin,
event.pageY - this.relativePosY - ymin
)
) {
// 在多边形内
let e = document.getElementById("shadowDiv");
e.style.display = "none";
}
},
showShadow(event) {
// 阴影显示
let e = event.currentTarget;
let type = e.shape;
let coords = e.coords.split(",");
let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
this.shadowHref = e.title;
let shadowDiv = document.getElementById("shadowDiv");
shadowDiv.style.display = "block";
if ("rect" == type) {
// area 是矩形 绘制 canvas 并遮罩该矩形
// 计算画布的宽高
this.canvasHeight = coords[3] - coords[1];
this.canvasWidth = coords[2] - coords[0];
c.width = this.canvasWidth;
c.height = this.canvasHeight;
// 矩形 直接使用 画布的宽高作为矩形的宽高
ctx.rect(0, 0, c.width, c.height);
// 设置阴影的div 的相对位置
shadowDiv.style.top = coords[1] + "px";
shadowDiv.style.left = coords[0] + "px";
}
if ("circle" == type) {
// 计算canvas的宽高即为 直径
this.canvasHeight = 2 * coords[2];
this.canvasWidth = 2 * coords[2];
ctx.beginPath();
// 绘制圆形
ctx.arc(coords[2], coords[2], coords[2], 0, 2 * Math.PI);
ctx.closePath();
// 设置阴影的div 的相对位置
shadowDiv.style.top = coords[1] - coords[2] + "px";
shadowDiv.style.left = coords[0] - coords[2] + "px";
}
if ("poly" == type) {
//将coords 转化为坐标点
// 取出最大的
let vs = [];
// 获取 多边形中 横坐标纵坐标的 最大最小值
let xmax = coords[0];
let xmin = coords[0];
let ymax = coords[1];
let ymin = coords[1];
for (var temp = 0; temp < coords.length; temp += 2) {
vs.unshift([coords[temp], coords[temp + 1]]);
xmax = xmax > coords[temp] ? xmax : coords[temp];
xmin = xmin > coords[temp] ? coords[temp] : xmin;
ymax = ymax > coords[temp + 1] ? ymax : coords[temp + 1];
ymin = ymin > coords[temp + 1] ? coords[temp + 1] : ymin;
}
// 计算 画布的高度
c.height = ymax - ymin;
// 计算 画布的宽度
c.width = xmax - xmin;
// 绘制多边形
ctx.beginPath();
ctx.moveTo(vs[0][0] - xmin, vs[0][1] - ymin);
for (var m = 1; m < vs.length; m++) {
ctx.lineTo(vs[m][0] - xmin, vs[m][1] - ymin);
}
ctx.closePath();
// 设置阴影的div 的相对位置
shadowDiv.style.top = ymin + "px";
shadowDiv.style.left = xmin + "px";
}
// 根据 设置的阴影颜色来设置矩形的填充色
ctx.fillStyle = this.shadowColor;
ctx.fill();
},
},
};
</script>
把父组件调用的代码也贴一下 咱就结束了
<template>
<div>
<hotspotShadow
shadowColor="rgba(0,100,200,0.5)"
:openType="openType"
:imgUrl="imgUrl"
:areas="areas"
></hotspotShadow>
</div>
</template>
<script >
import hotspotShadow from "./hotspot-shadow.vue";
export default {
components: {
hotspotShadow,
},
data() {
return {
openType: "self",
imgUrl: require("../../assets/3.jpg"),
areas: [
{
type: "circle",
coord: "260,60,70",
href: "http://www.baidu.com",
},
{
type: "rect",
coord: "23,145,393,345",
href: "http://www.baidu.com",
},
{
type: "rect",
coord: "400,145,522,383",
href: "http://www.baidu.com",
},
{
type: "rect",
coord: "23,345,393,532",
href: "http://www.baidu.com",
},
{
type: "rect",
coord: "400,401,522,630",
href: "http://www.baidu.com",
},
{
type: "poly",
coord: "23,535,393,535,393,630,522,636,522,765,23,765",
href: "http://www.newlixon.com",
},
],
};
},
};
</script>