有没有一种方法可以在不直接操作DOM的情况下使用d3轴?
我目前正在使用一个简单的Vue模板来生成SVG.
我希望避免使用d3.select
来防止直接修改DOM.它运行良好,但与Vue冲突.js的范围样式.
有没有一种方法可以在不从DOM元素调用的情况下访问d3-axis
?如果能够独立地访问其path
生成函数,而不是通过DOM访问,这将非常有用.
下面是一个示例代码笔:https://codepen.io/thibautg/pen/BYRBXW
有没有一种方法可以在不直接操作DOM的情况下使用d3轴?
我目前正在使用一个简单的Vue模板来生成SVG.
我希望避免使用d3.select
来防止直接修改DOM.它运行良好,但与Vue冲突.js的范围样式.
有没有一种方法可以在不从DOM元素调用的情况下访问d3-axis
?如果能够独立地访问其path
生成函数,而不是通过DOM访问,这将非常有用.
下面是一个示例代码笔:https://codepen.io/thibautg/pen/BYRBXW
这种情况需要custom directive美元.自定义指令允许您在它们附加到的元素中操作DOM.
在本例中,我创建了一个指令,它接受一个参数,该参数的轴和一个值是您计算的比例.根据轴是x还是y,它用scale[axis]
调用axisBottom
或axisLeft
.
别再看了.该指令将在任何更新时调用.如果你愿意的话,你可以判断一下scale
是否与之前的值相比发生了变化.
new Vue({
el: "#app",
data() {
return {
width: 600,
height: 400,
margin: {
top: 20,
right: 20,
bottom: 20,
left: 20
},
items: [
{ name: "a", val: 10 },
{ name: "b", val: 8 },
{ name: "c", val: 1 },
{ name: "d", val: 5 },
{ name: "e", val: 6 },
{ name: "f", val: 3 }
]
};
},
computed: {
outsideWidth() {
return this.width + this.margin.left + this.margin.right;
},
outsideHeight() {
return this.height + this.margin.top + this.margin.bottom;
},
scale() {
const x = d3
.scaleBand()
.domain(this.items.map(x => x.name))
.rangeRound([0, this.width])
.padding(0.15);
const y = d3
.scaleLinear()
.domain([0, Math.max(...this.items.map(x => x.val))])
.rangeRound([this.height, 0]);
return { x, y };
}
},
directives: {
axis(el, binding) {
const axis = binding.arg;
const axisMethod = { x: "axisBottom", y: "axisLeft" }[axis];
const methodArg = binding.value[axis];
d3.select(el).call(d3[axisMethod](methodArg));
}
}
});
rect.bar {
fill: steelblue;
}
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<div id="app">
<svg :width="outsideWidth"
:height="outsideHeight">
<g :transform="`translate(${margin.left},${margin.top})`">
<g class="bars">
<template v-for="item in items">
<rect class="bar"
:x="scale.x(item.name)"
:y="scale.y(item.val)"
:width="scale.x.bandwidth()"
:height="height - scale.y(item.val)"
/>
</template>
<g v-axis:x="scale" :transform="`translate(0,${height})`"></g>
<g v-axis:y="scale"></g>
</g>
</g>
</svg>
</div>