废话不多说直接上代码
模板
源数据格式,小编用得是动态数据就不给大家展示了就放个格式给大家看看吧
data = [
{
letter: "白皮鸡蛋",
child: {
category: "0",
value: "459.00"
}
},
{
letter: "红皮鸡蛋",
child: {
category: "0",
value: "389.00"
}
},....]
接下来是重点啊代码有点多(前方高能)
d3在vue中安装也很简单 直接 npm install d3
import * as d3 from "d3";
我是封装在chart函数中的(两个参数分别是源数据和图像挂载dom在vue中直接用this.$refs.cil其他地方的用法和JQ类似)
function chart(data, myEle) {
{
var margin = {
top: 20,
right: 50,
bottom: 50,
left: 90
};
var svgWidth = window.screen.width -margin.right -margin.left; // 检测屏幕
var svgHeight = 500;
//创建各个面的颜色数组
var mainColorList = [
"#f6e242",
"#ebec5b",
"#d2ef5f",
"#b1d894",
"#97d5ad",
"#82d1c0",
"#70cfd2",
"#63c8ce",
"#50bab8",
"#38a99d"
];
var topColorList = [
"#e9d748",
"#d1d252",
"#c0d75f",
"#a2d37d",
"#83d09e",
"#68ccb6",
"#5bc8cb",
"#59c0c6",
"#3aadab",
"#2da094"
];
var rightColorList = [
"#dfce51",
"#d9db59",
"#b9d54a",
"#9ece7c",
"#8ac69f",
"#70c3b1",
"#65c5c8",
"#57bac0",
"#42aba9",
"#2c9b8f"
];
// console.log(this.$refs.cil)
var svg = d3
.select(myEle)
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("id", "svg-column");
// 创建X轴序数比例尺
function addXAxis() {
var transform = d3.geoTransform({
point: function (x, y) {
this.stream.point(x, y);
}
}); //定义几何路径
var path = d3.geoPath().projection(transform);
var xLinearScale = d3
.scaleBand()
.domain(
data.map(function (d) {
return d.letter;
})
)
.range([0, svgWidth - margin.right - margin.left], 0.1);
var xAxis = d3.axisBottom(xLinearScale).ticks(data.length); //绘制X轴
var xAxisG = svg
.append("g")
.call(xAxis)
.attr(
"transform",
"translate(" + margin.left + "," + (svgHeight - margin.bottom) +")"
); //删除原X轴
xAxisG.select("path").remove();
xAxisG.selectAll("line").remove(); //绘制新的立体X轴
xAxisG
.append("path")
.datum({
type: "Polygon",
coordinates: [
[
[20, 0],
[0, 15],
[svgWidth - margin.right - margin.left, 15],
[svgWidth + 20 - margin.right - margin.left, 0],
[20, 0]
]
]
})
.attr("d", path)
.attr("fill", "rgb(187,187,187)");
xAxisG
.selectAll("text")
.attr("fill", "#646464")
.attr("class", 'rotate_txt')
.attr("transform-origin", "50% top 0")
.attr("transform", "translate(0,20)");
dataProcessing(xLinearScale); //核心算法
}
var yLinearScale;
//创建y轴的比例尺渲染y轴
function addYScale() {
yLinearScale = d3
.scaleLinear()
.domain([
0,
d3.max(data, function (d, i) {
return d.child.value * 1;
}) * 1.2
])
.range([svgHeight - margin.top - margin.bottom, 0]);
//定义Y轴比例尺以及刻度
var yAxis = d3.axisLeft(yLinearScale).ticks(6);
//绘制Y轴
var yAxisG = svg
.append("g")
.call(yAxis)
.attr(
"transform",
"translate(" + (margin.left + 10) + "," + margin.top + ")"
);
yAxisG
.selectAll("text")
.attr("font-size", "18px")
.attr("fill", "#636363");
//删除原Y轴路径和tick
yAxisG.select("path").remove();
yAxisG.selectAll("line").remove();
}
//核心算法思路是
function dataProcessing(xLinearScale) {
var angle = Math.PI / 2.3;
for (var i = 0; i < data.length; i++) {
var d = data[i];
var depth = 10;
d.ow = xLinearScale.bandwidth() * 0.7;
d.ox = xLinearScale(d.letter);
d.oh = 1;
d.p1 = {
x: Math.cos(angle) * d.ow,
y: -Math.sin(angle) - depth
};
d.p2 = {
x: d.p1.x + d.ow,
y: d.p1.y
};
d.p3 = {
x: d.p2.x,
y: d.p2.y + d.oh
};
}
}
//tip的创建方法
var tipTimerConfig = {
longer: 0,
target: null,
exist: false,
winEvent: window.event,
boxHeight: 398,
boxWidth: 376,
maxWidth: 376,
maxHeight: 398,
tooltip: null,
showTime: 3500,
hoverTime: 300,
displayText: "",
show: function (val, e) {
"use strict";
var me = this;
if (e != null) {
me.winEvent = e;
}
me.displayText = val;
me.calculateBoxAndShow();
me.createTimer();
},
calculateBoxAndShow: function () {
"use strict";
var me = this;
var _x = 0;
var _y = 0;
var _w = document.documentElement.scrollWidth;
var _h = document.documentElement.scrollHeight;
var wScrollX = window.scrollX || document.body.scrollLeft;
var wScrollY = window.scrollY || document.body.scrollTop;
var xMouse = me.winEvent.x + wScrollX;
if (_w - xMouse < me.boxWidth) {
_x = xMouse - me.boxWidth - 10;
} else {
_x = xMouse;
}
var _yMouse = me.winEvent.y + wScrollY;
if (_h - _yMouse < me.boxHeight + 18) {
_y = _yMouse - me.boxHeight - 25;
} else {
_y = _yMouse + 18;
}
me.addTooltip(_x, _y);
},
addTooltip: function (page_x, page_y) {
"use strict";
var me = this;
me.tooltip = document.createElement("div");
me.tooltip.style.left = page_x + "px";
me.tooltip.style.top = page_y + "px";
me.tooltip.style.position = "absolute";
me.tooltip.style.width = me.boxWidth + "px";
me.tooltip.style.height = me.boxHeight + "px";
me.tooltip.className = "three-tooltip";
var divInnerHeader = me.createInner();
divInnerHeader.innerHTML = me.displayText;
me.tooltip.appendChild(divInnerHeader);
document.body.appendChild(me.tooltip);
},
createInner: function () {
"use strict";
var me = this;
var divInnerHeader = document.createElement("div");
divInnerHeader.style.width = me.boxWidth + "px";
divInnerHeader.style.height = me.boxHeight + "px";
return divInnerHeader;
},
ClearDiv: function () {
"use strict";
var delDiv = document.body.getElementsByClassName("three-tooltip");
for (var i = delDiv.length - 1; i >= 0; i--) {
document.body.removeChild(delDiv[i]);
}
},
createTimer: function (delTarget) {
"use strict";
var me = this;
var delTip = me.tooltip;
var delTarget = tipTimerConfig.target;
var removeTimer = window.setTimeout(function () {
try {
if (delTip != null) {
document.body.removeChild(delTip);
if (tipTimerConfig.target == delTarget) {
me.exist = false;
}
}
clearTimeout(removeTimer);
} catch (e) {
clearTimeout(removeTimer);
}
}, me.showTime);
},
hoverTimerFn: function (showTip, showTarget) {
"use strict";
var me = this;
var showTarget = tipTimerConfig.target;
var hoverTimer = window.setInterval(function () {
try {
if (tipTimerConfig.target != showTarget) {
clearInterval(hoverTimer);
} else if (
!tipTimerConfig.exist &&
new Date().getTime() - me.longer > me.hoverTime
) {
//show
tipTimerConfig.show(showTip);
tipTimerConfig.exist = true;
clearInterval(hoverTimer);
}
} catch (e) {
clearInterval(hoverTimer);
}
}, tipTimerConfig.hoverTime);
}
};
var createTooltipTableData = function (info) {
var ary = [];
ary.push("<div class='tip-hill-div'>");
ary.push("<p>" + info.letter +' '+ info.child.value + "</p>");
ary.push("</div>");
return ary.join("");
};
// 核心算法写完,就到了最终的渲染了
function addColumn() {
function clumnMouseover(d) {
d3.select(this)
.selectAll(".transparentPath")
.attr("opacity", 0.8);
// 添加 div
tipTimerConfig.target = this;
tipTimerConfig.longer = new Date().getTime();
tipTimerConfig.exist = false;
//获取坐标
tipTimerConfig.winEvent = {
x: event.clientX - 100,
y: event.clientY
};
tipTimerConfig.boxHeight = 50;
tipTimerConfig.boxWidth = 140;
//hide
tipTimerConfig.ClearDiv();
//show
tipTimerConfig.hoverTimerFn(createTooltipTableData(d));
}
function clumnMouseout(d) {
d3.select(this)
.selectAll(".transparentPath")
.attr("opacity", 1);
tipTimerConfig.target = null;
tipTimerConfig.ClearDiv();
}
var g = svg
.selectAll(".g")
.data(data)
.enter()
.append("g")
.on("mouseover", clumnMouseover)
.on("mouseout", clumnMouseout)
.attr("transform", function (d) {
return (
"translate(" +
(d.ox + margin.left + 20) +
"," +
(svgHeight - margin.bottom + 15) +
")"
);
});
g.transition()
.duration(2500)
.attr("transform", function (d) {
return (
"translate(" +
(d.ox + margin.left + 20) +
", " +
(yLinearScale(d.child.value) + margin.bottom - 15) +
")"
);
});
g.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("class", "transparentPath")
.attr("width", function (d, i) {
return d.ow;
})
.attr("height", function (d) {
return d.oh;
})
.style("fill", function (d, i) {
if (!mainColorList[i]) {
return "#38a99d"
}
return mainColorList[i];
})
.transition()
.duration(2500)
.attr("height", function (d, i) {
return (
svgHeight -
margin.bottom -
margin.top -
yLinearScale(d.child.value)
);
});
g.append("path")
.attr("class", "transparentPath")
.attr("d", function (d) {
return (
"M0,0 L" +
d.p1.x +
"," +
d.p1.y +
" L" +
d.p2.x +
"," +
d.p2.y +
" L" +
d.ow +
",0 L0,0"
);
})
.style("fill", function (d, i) {
if (!topColorList[i]) {
return "#2da094"
}
return topColorList[i];
});
g.append("path")
.attr("class", "transparentPath")
.attr("d", function (d) {
return (
"M" +
d.ow +
",0 L" +
d.p2.x +
"," +
d.p2.y +
" L" +
d.p3.x +
"," +
d.p3.y +
" L" +
d.ow +
"," +
d.oh +
" L" +
d.ow +
",0"
);
})
.style("fill", function (d, i) {
if (!rightColorList[i]) {
return "#2c9b8f"
}
return rightColorList[i];
})
.transition()
.duration(2500)
.attr("d", function (d, i) {
return (
"M" +
d.ow +
",0 L" +
d.p2.x +
"," +
d.p2.y +
" L" +
d.p3.x +
"," +
(d.p3.y +
svgHeight -
margin.top -
margin.bottom -
yLinearScale(d.child.value)) +
" L" +
d.ow +
"," +
(svgHeight -
margin.top -
margin.bottom -
yLinearScale(d.child.value)) +
" L" +
d.ow +
",0"
);
});
}
// 函数调用
addXAxis();
addYScale();
addColumn();
}
}
这里提供暴露接口让组件调用
export function showCahrt(data, myEle) {
return chart(data, myEle)
}
这里有个bug我一直没有找到很好的解决办法就是在绘制x轴时文字的样式调整
就是这里使用.attr("transform", "translate(0,20) rotate(-30deg)")也就是旋转加下移组合是根本不生效只能写其中的一个。不知道小伙伴们有没有什么高见很是期待!
整篇的代码有点长其实整体还是很清晰的 。在最后面
有收获的小朋友记得点赞哦
本文暂时没有评论,来添加一个吧(●'◡'●)