javascript - 减少代码 - 附加 svg 图像的重复代码

标签 javascript d3.js svg

我有一个 svg 图,其中包含几种不同类型的节点,每种类型都有许多具有不同用途的不同节点。

产品, 社区, 事件, 项目, 产品组。

我想设置每个节点的背景图片。

每个组的每个单独节点都有其自己的唯一 ID。 这些节点的类型和 ID 可用于从端点检索所有类型的图像,但图像位于 Assets 文件夹中的产品组除外。

我正在尝试从 1. 端点和 2. 从 Assets 文件夹调用图像。

我的端点代表不同的类型并解析 ID:

https://tiktok.org/products/${node.id}/standard

https://tiktok.org/communities/${node.id}/standard

我目前的方法似乎效率极低,而且我不应该有重复的代码!我“附加”一个 svg 图像和一个 ID,然后我将它们引用为 node.types 并解析它们的 ID,但这只是大量代码(以两种类型为例):

   .selectAll('circle.node')
    .data(this.nodes)
    .enter();
  //products
  circle
    .filter(node => node.type === EngagementType.Product)
    .append("pattern")
    .attr("id", d => `insightImage-${d.id}`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", d => `https://tiktok.org/products/${d.id}/standard`) (fake link)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice');
  //communities
  circle
    .filter(node => node.type === EngagementType.Community)
    .append("pattern")
    .attr("id", d => `insightImageCom-${d.id}`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", d => `https://tiktok.org/communities/${d.id}/standard`)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice');

然后我用样式属性填充圆圈,如下所示:

  circle
    .filter(node => node.depth !== 0 && node.type === EngagementType.Product)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node && (node.depth === 4 && !node.isExtraNode))
    .style('fill', d => `url(#insightImage-${d.id})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));
  circle
    .filter(node => node.depth !== 0 && node.type === EngagementType.Community)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node && (node.depth === 4 && !node.isExtraNode))
    .style('fill', d => `url(#insightImageCom-${d.id})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));

我对 Assets 文件夹中的图像有类似的方法,我有一堆images.svg,然后对产品组执行与上面相同的操作,但实际上单独调用它们占用了大量空间......

在本例中,我通过节点的 ID 调用节点来单独分配 Assets 文件夹中的图像:

      circle
    .filter(node => node.type === EngagementType.ProductGroup && node.id === 'a6qb000000003olAAA')
    .append("pattern")
    .attr("id", `insightImageInitiative`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", './assets/d3-icons/initiative.svg')
    .attr("x", 0.2)
    .attr("y", 0.2)
    .attr("width", 0.60)
    .attr("height", 0.60)
    .attr('preserveAspectRatio', 'xMidYMid slice');
  circle
    .filter(node => node.type === EngagementType.ProductGroup && node.id === 'a6qb000000003okAAA')
    .append("pattern")
    .attr("id", `insightImageIndustry`)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0)
    .append("image")
    .attr("xlink:href", './assets/d3-icons/industry.svg')
    .attr("x", 0.2)
    .attr("y", 0.2)
    .attr("width", 0.60)
    .attr("height", 0.60)
    .attr('preserveAspectRatio', 'xMidYMid slice');

我尝试简单地使用样式(填充),但它对我不起作用!!

    .style('fill', d => `url('./assets/d3-icons/calendar.svg')`) 
    .style('fill', d => `url('https://tiktok.org/products/${d.id}/standard')`) 

什么也没出现!

关于如何以不同方式设置图像或如何消除大量重复的一些建议/帮助将是惊人的!

我确信有一种更简单的方法来设置背景图像,当然端点是不同的。

感谢您的帮助!

最佳答案

您使用的数据对象可以是任何东西。最合适的模式是在将其附加到元素选择之前对其进行准备,这样您就已经拥有了所需的一切。

以下示例定义了从类型到每个类别不同的​​数据的数据结构映射。这只是一个示例,核心是 .map() 函数中发生的事情:向数据对象添加一个或多个属性,以便在 node.type< 之间建立连接 以及您需要为每个节点编写正确的模式的方式。

需要使用类似的方法从 ids 连接到资源文件夹图像。

有点奇怪的是,你为每个节点定义了一个模式,但只在 node.depth !== 0 的情况下画一个圆圈,但这只是为了让你理解,仅使用过滤功能识别需要渲染圆圈的非顶级条目。

const details = new Map([
    [EngagementType.Product, { path: 'products', prefix: 'insightImage'} ],
    [EngagementType.Community, { path: 'comunities', prefix: 'insightImageCom'} ],
    // and so on...
]);

// enhance your data, each node is a shallow copy with extra properties
const renderingData = this.nodes.map(node => Object.assign({
    patternId: `${details.get(node.type).prefix}-${d.id}`,
    imageUrl: `https://tiktok.org/${details.get(node.type).path}/${d.id}/standard`,
    isLeaf: node.depth === 4 && !node.isExtraNode
}, node));

const circle = d3.selectAll('circle.node')
    .data(renderingData)
    .enter();

// now it is straight forward
circle
    .append("pattern")
    .attr("id", d => node.patternId)
    .attr("patternContentUnits", "objectBoundingBox")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", 0)
    .attr("y", 0);
    .append("image")
    .attr("xlink:href", d => d.imageUrl)
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr('preserveAspectRatio', 'xMidYMid slice')
  // and now you filter for non-toplevel nodes
  .filter(node => node.depth !== 0)
    .append('circle')
    .classed('Engagement-GraphNode', true)
    .classed('Engagement-GraphNodeBackground', true)
    .classed('Engagement-GraphLeaf', node => node.isLeaf)
    .style('fill', d => `url(#${d.patternId})`)
    .style('opacity', node => (node.visible) ? 1 : 0)
    .style('visibility', node => (node.visible) ? 'visible' : 'hidden')
    .on('click', node => onClick(node));

关于javascript - 减少代码 - 附加 svg 图像的重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54652728/

相关文章:

javascript - 根据下拉值显示元素数量的问题

javascript - 如何使用 javascript 从页面获取源代码

javascript - 自动将 svg 中的形状转换为按钮以显示附加信息

CHM 中的 SVG 图形(Html 帮助研讨会)

javascript - 通过滚动移动文本

javascript - Javascript foreach 异步行为问题

javascript - 访问具有空格的 JSON 对象键

d3.js - dc.js 中的双 Y 轴折线图

javascript - 页面仅显示 2 个图表中的 1 个

javascript - 单击下一步按钮时按钮内容关闭