如何使用 React 在标签中设置 img?
How to set img in label using React?
我正在使用 react-chartist
创建图表。在标签上,我想在标签文本旁边添加图像。我尝试了所有想法,但 none 奏效了。一切 return [object Object]
。这个问题是否有好的解决方案?我也可以只使用 css
添加标签,但如果我可以在 <Chartist />
组件中添加标签,那就容易多了。
我尝试的简单代码示例(下面的 codesandbox 演示):
class Chart extends React.Component {
render() {
const labels = ["label 1", "label 2", "label 3"];
const images = [
"http://placekitten.com/100/100",
"http://placekitten.com/101/101",
"http://placekitten.com/102/102"
];
const series = [[40, 30, 20]];
const labelsInsideReactFragment = labels.map((el, key) => (
<React.Fragment>
<img src={images[key]} /> {el}
</React.Fragment>
));
const labelsViaGhIssue = labels.map((el, key) => {
return {
label: el,
image: images[key]
};
});
const labelsInsideDiv = labels.map((el, key) => (
<div>
<img src={images[key]} /> {el}
</div>
));
const labelsOnlyImg = labels.map((el, key) => <img src={images[key]} />);
const data1 = {
labels,
series
};
const data2 = {
labels: labelsViaGhIssue,
series
};
const data3 = {
labels: labelsInsideDiv,
series
};
const data4 = {
labels: labelsInsideReactFragment,
series
};
const data5 = {
labels: labelsOnlyImg,
series
};
const options = {
height: "200px",
width: "500px"
};
return (
<div>
<ChartistGraph data={data1} options={options} type="Bar" />
<ChartistGraph data={data2} options={options} type="Bar" />
<ChartistGraph data={data3} options={options} type="Bar" />
<ChartistGraph data={data4} options={options} type="Bar" />
<ChartistGraph data={data5} options={options} type="Bar" />
</div>
);
}
}
演示:https://codesandbox.io/s/chartist-8oeju
我也在 jsbin
上找到了这个演示:https://jsbin.com/gulokelide/edit?js,output
但我猜它在 React
中不起作用。
根据你给的jsbinlink,我们也可以更新react版本
检查我创建的新沙箱。
https://codesandbox.io/s/chartist-m1yv9
方法是:每个 React chartist 组件都附加了它的 chartist 对象。所以添加一个 ref 来捕获它并从每个图表的上下文更新标签,就像 jsbin 示例一样。
import Chartist from "chartist";
//in componentDidMount()
const chart = this.refTwo.current;
chart.chartist.on("draw", context => {
if (context.type === "label" && context.axis.units.pos === "x") {
if (context.text && context.text.image) {
const group = new Chartist.Svg("g");
group.append(
new Chartist.Svg("image", {
"xlink:href": context.text.image,
width: "30px",
height: "30px",
x: context.x + 55,
y: context.y + 5
})
);
context.element.replace(group);
}
}
});
// in render()
<ChartistGraph
ref={this.refTwo}
data={data2}
options={options}
type="Bar"
/>
您好,您可以对以下元素执行 "on draw":
<ChartistGraph
listener={{
draw: e => this.onDrawHandler(e)
}}
data={data2}
options={options}
type="Bar"
/>
并执行您的 class 方法:
onDrawHandler = context => {
//...code
}
示例如下:
JSbin 示例使用了 react-chartist
不支持的自定义 on("draw")
函数(并且它还在手动计算标签位置,因此如果宽度或数量不会缩放系列中的数据变化)。也就是说,最简单的解决方案是制作您自己的 Chartist
实例并根据您的需要对其进行更改。
工作示例(无论宽度如何,标签和图像都会缩放到中心 and/or series
中的项目数):
components/Chart
import React, { Component, cloneElement, Children } from "react";
import Chartist from "chartist";
import PropTypes from "prop-types";
class Chart extends Component {
componentDidUpdate(prevProps) {
if (this.props !== prevProps) this.updateChart(this.props);
}
componentWillUnmount() {
if (this.chart) {
try {
this.chart.detach();
} catch (err) {
throw new Error("Internal chartist error", err);
}
}
}
componentDidMount = () => this.updateChart(this.props);
updateChart = ({ data, listener, options, responsiveOptions, type }) => {
let event;
if (this.chartist) {
this.chart.update(data, options, responsiveOptions);
} else {
this.chart = new Chartist[type](
this.chart,
data,
options || {},
responsiveOptions || []
).on("draw", context => {
if (type === "Pie") return;
if (context.type === "label" && context.axis.units.pos === "x") {
if (context && context.text) {
const group = new Chartist.Svg("g");
const isBar = type === "Bar";
const hasImage = context.text.image;
const hasLabel = context.text.label;
if (hasImage) {
const x = isBar
? context.x + context.width / 2 - 15
: context.x + 5;
const y = isBar
? context.y + context.height / 2 - 10
: context.y + 0;
group.append(
new Chartist.Svg("image", {
"xlink:href": context.text.image,
width: "30px",
height: "30px",
x,
y
})
);
}
if (hasLabel) {
const x = isBar
? context.x + context.width / 2 + 5
: context.x + 30;
const y = hasImage
? context.y + context.height / 2 + 30
: context.y + context.height / 2;
group.append(
new Chartist.Svg("text", {
width: "100px",
height: "40px",
x,
y,
"text-anchor": "middle",
"alignment-baseline": "hanging"
}).text(context.text.label || "")
);
}
context.element.replace(group);
}
}
});
if (listener) {
for (event in listener) {
if (listener.hasOwnProperty(event)) {
this.chart.on(event, listener[event]);
}
}
}
}
return this.chart;
};
render = () => {
const { className, style, children, data, type } = this.props;
const childrenWithProps =
children &&
Children.map(children, child =>
cloneElement(child, {
type,
data
})
);
return (
<div
className={`ct-chart ${className || ""}`}
ref={ref => (this.chart = ref)}
style={style}
>
{childrenWithProps}
</div>
);
};
}
Chart.propTypes = {
type: PropTypes.oneOf(["Line", "Bar", "Pie"]).isRequired,
data: PropTypes.object.isRequired,
className: PropTypes.string,
options: PropTypes.object,
responsiveOptions: PropTypes.array,
style: PropTypes.object
};
export default Chart;
我正在使用 react-chartist
创建图表。在标签上,我想在标签文本旁边添加图像。我尝试了所有想法,但 none 奏效了。一切 return [object Object]
。这个问题是否有好的解决方案?我也可以只使用 css
添加标签,但如果我可以在 <Chartist />
组件中添加标签,那就容易多了。
我尝试的简单代码示例(下面的 codesandbox 演示):
class Chart extends React.Component {
render() {
const labels = ["label 1", "label 2", "label 3"];
const images = [
"http://placekitten.com/100/100",
"http://placekitten.com/101/101",
"http://placekitten.com/102/102"
];
const series = [[40, 30, 20]];
const labelsInsideReactFragment = labels.map((el, key) => (
<React.Fragment>
<img src={images[key]} /> {el}
</React.Fragment>
));
const labelsViaGhIssue = labels.map((el, key) => {
return {
label: el,
image: images[key]
};
});
const labelsInsideDiv = labels.map((el, key) => (
<div>
<img src={images[key]} /> {el}
</div>
));
const labelsOnlyImg = labels.map((el, key) => <img src={images[key]} />);
const data1 = {
labels,
series
};
const data2 = {
labels: labelsViaGhIssue,
series
};
const data3 = {
labels: labelsInsideDiv,
series
};
const data4 = {
labels: labelsInsideReactFragment,
series
};
const data5 = {
labels: labelsOnlyImg,
series
};
const options = {
height: "200px",
width: "500px"
};
return (
<div>
<ChartistGraph data={data1} options={options} type="Bar" />
<ChartistGraph data={data2} options={options} type="Bar" />
<ChartistGraph data={data3} options={options} type="Bar" />
<ChartistGraph data={data4} options={options} type="Bar" />
<ChartistGraph data={data5} options={options} type="Bar" />
</div>
);
}
}
演示:https://codesandbox.io/s/chartist-8oeju
我也在 jsbin
上找到了这个演示:https://jsbin.com/gulokelide/edit?js,output
但我猜它在 React
中不起作用。
根据你给的jsbinlink,我们也可以更新react版本
检查我创建的新沙箱。
https://codesandbox.io/s/chartist-m1yv9
方法是:每个 React chartist 组件都附加了它的 chartist 对象。所以添加一个 ref 来捕获它并从每个图表的上下文更新标签,就像 jsbin 示例一样。
import Chartist from "chartist";
//in componentDidMount()
const chart = this.refTwo.current;
chart.chartist.on("draw", context => {
if (context.type === "label" && context.axis.units.pos === "x") {
if (context.text && context.text.image) {
const group = new Chartist.Svg("g");
group.append(
new Chartist.Svg("image", {
"xlink:href": context.text.image,
width: "30px",
height: "30px",
x: context.x + 55,
y: context.y + 5
})
);
context.element.replace(group);
}
}
});
// in render()
<ChartistGraph
ref={this.refTwo}
data={data2}
options={options}
type="Bar"
/>
您好,您可以对以下元素执行 "on draw":
<ChartistGraph
listener={{
draw: e => this.onDrawHandler(e)
}}
data={data2}
options={options}
type="Bar"
/>
并执行您的 class 方法:
onDrawHandler = context => {
//...code
}
示例如下:
JSbin 示例使用了 react-chartist
不支持的自定义 on("draw")
函数(并且它还在手动计算标签位置,因此如果宽度或数量不会缩放系列中的数据变化)。也就是说,最简单的解决方案是制作您自己的 Chartist
实例并根据您的需要对其进行更改。
工作示例(无论宽度如何,标签和图像都会缩放到中心 and/or series
中的项目数):
components/Chart
import React, { Component, cloneElement, Children } from "react";
import Chartist from "chartist";
import PropTypes from "prop-types";
class Chart extends Component {
componentDidUpdate(prevProps) {
if (this.props !== prevProps) this.updateChart(this.props);
}
componentWillUnmount() {
if (this.chart) {
try {
this.chart.detach();
} catch (err) {
throw new Error("Internal chartist error", err);
}
}
}
componentDidMount = () => this.updateChart(this.props);
updateChart = ({ data, listener, options, responsiveOptions, type }) => {
let event;
if (this.chartist) {
this.chart.update(data, options, responsiveOptions);
} else {
this.chart = new Chartist[type](
this.chart,
data,
options || {},
responsiveOptions || []
).on("draw", context => {
if (type === "Pie") return;
if (context.type === "label" && context.axis.units.pos === "x") {
if (context && context.text) {
const group = new Chartist.Svg("g");
const isBar = type === "Bar";
const hasImage = context.text.image;
const hasLabel = context.text.label;
if (hasImage) {
const x = isBar
? context.x + context.width / 2 - 15
: context.x + 5;
const y = isBar
? context.y + context.height / 2 - 10
: context.y + 0;
group.append(
new Chartist.Svg("image", {
"xlink:href": context.text.image,
width: "30px",
height: "30px",
x,
y
})
);
}
if (hasLabel) {
const x = isBar
? context.x + context.width / 2 + 5
: context.x + 30;
const y = hasImage
? context.y + context.height / 2 + 30
: context.y + context.height / 2;
group.append(
new Chartist.Svg("text", {
width: "100px",
height: "40px",
x,
y,
"text-anchor": "middle",
"alignment-baseline": "hanging"
}).text(context.text.label || "")
);
}
context.element.replace(group);
}
}
});
if (listener) {
for (event in listener) {
if (listener.hasOwnProperty(event)) {
this.chart.on(event, listener[event]);
}
}
}
}
return this.chart;
};
render = () => {
const { className, style, children, data, type } = this.props;
const childrenWithProps =
children &&
Children.map(children, child =>
cloneElement(child, {
type,
data
})
);
return (
<div
className={`ct-chart ${className || ""}`}
ref={ref => (this.chart = ref)}
style={style}
>
{childrenWithProps}
</div>
);
};
}
Chart.propTypes = {
type: PropTypes.oneOf(["Line", "Bar", "Pie"]).isRequired,
data: PropTypes.object.isRequired,
className: PropTypes.string,
options: PropTypes.object,
responsiveOptions: PropTypes.array,
style: PropTypes.object
};
export default Chart;