Skip to content

Commit

Permalink
Merge pull request #386 from multinet-app/fix-attribute-layout
Browse files Browse the repository at this point in the history
Fix node positioning and axes on attribute driven layouts
  • Loading branch information
JackWilb authored Sep 6, 2023
2 parents b465cca + 49f815d commit 892bafb
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 22 deletions.
35 changes: 16 additions & 19 deletions src/components/MultiLink.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import {
scaleBand, scaleLinear, ScaleLinear,
scalePoint, scaleLinear, ScaleLinear,
forceLink, forceManyBody, forceSimulation, forceX, forceY,
select, axisBottom, axisLeft,
select, axisBottom, axisLeft, forceCollide,
} from 'd3';
import {
computed, onMounted, ref, watch,
Expand Down Expand Up @@ -525,11 +525,18 @@ function resetSimulationForces() {
applyForceToSimulation(
simulation.value,
'charge',
forceManyBody().strength(-120),
forceManyBody().strength(-100),
);
applyForceToSimulation(
simulation.value,
'collision',
forceCollide<Node>((d) => calculateNodeSize(d) / 2),
);
}
}
watch([markerSize, nodeSizeVariable], resetSimulationForces);
const xAxisPadding = 60;
const yAxisPadding = 80;
function makePositionScale(axis: 'x' | 'y', type: ColumnType, range: AttributeRange) {
Expand Down Expand Up @@ -579,16 +586,16 @@ function makePositionScale(axis: 'x' | 'y', type: ColumnType, range: AttributeRa
positionScale = scaleLinear()
.domain([minValue, maxValue]);
} else {
positionScale = scaleBand()
positionScale = scalePoint()
.domain(range.binLabels);
}
if (axis === 'x') {
const minMax = [clipLow ? yAxisPadding + clipRegionSize : yAxisPadding, clipHigh ? svgDimensions.value.width - clipRegionSize : svgDimensions.value.width];
const minMax = [clipLow ? yAxisPadding + clipRegionSize : yAxisPadding, (clipHigh ? svgDimensions.value.width - clipRegionSize : svgDimensions.value.width) - 10];
positionScale = positionScale
.range(minMax);
} else {
const minMax = [clipLow ? svgDimensions.value.height - xAxisPadding - clipRegionSize : svgDimensions.value.height - xAxisPadding, clipHigh ? clipRegionSize : 0];
const minMax = [clipLow ? svgDimensions.value.height - xAxisPadding - clipRegionSize : svgDimensions.value.height - xAxisPadding, (clipHigh ? clipRegionSize : 0) - 10];
positionScale = positionScale
.range(minMax);
}
Expand All @@ -597,8 +604,6 @@ function makePositionScale(axis: 'x' | 'y', type: ColumnType, range: AttributeRa
if (varName !== null) {
if (columnTypes.value !== null) {
const otherAxisPadding = axis === 'x' ? 80 : 60;
if (type === 'number') {
const scaleDomain = positionScale.domain();
const scaleRange = positionScale.range();
Expand All @@ -623,15 +628,7 @@ function makePositionScale(axis: 'x' | 'y', type: ColumnType, range: AttributeRa
}
});
} else {
let positionOffset: number;
if (axis === 'x') {
positionOffset = (svgDimensions.value.width - otherAxisPadding) / ((range.binLabels.length) * 2);
} else {
positionOffset = ((svgDimensions.value.height - xAxisPadding) / ((range.binLabels.length) * 2)) - 10;
}
const force = axis === 'x' ? forceX<Node>((d) => positionScale(d[varName]) + positionOffset).strength(1) : forceY<Node>((d) => positionScale(d[varName]) + positionOffset).strength(1);
const force = axis === 'x' ? forceX<Node>((d) => positionScale(d[varName]) - (calculateNodeSize(d) / 2)).strength(2) : forceY<Node>((d) => positionScale(d[varName]) - (calculateNodeSize(d) / 2)).strength(2);
applyForceToSimulation(
simulation.value,
axis,
Expand Down Expand Up @@ -811,8 +808,6 @@ onMounted(() => {
stroke-dasharray="5,5"
/>

<g id="axes" />

<!-- High and low clip regions -->
<g>
<g
Expand Down Expand Up @@ -998,6 +993,8 @@ onMounted(() => {
</g>
</g>
</g>

<g id="axes" />
</svg>

<div
Expand Down
6 changes: 3 additions & 3 deletions src/lib/d3ForceUtils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
ForceManyBody, ForceLink, Simulation, ForceX, ForceY,
ForceManyBody, ForceLink, Simulation, ForceX, ForceY, ForceCollide,
} from 'd3';
import { Node, SimulationEdge } from '@/types';

export function applyForceToSimulation(
simulation: Simulation<Node, SimulationEdge> | null,
forceType: 'x' | 'y' | 'charge' | 'edge',
forceValue: ForceX<Node> | ForceY<Node> | ForceManyBody<Node> | ForceLink<Node, SimulationEdge> | undefined,
forceType: 'x' | 'y' | 'charge' | 'edge' | 'collision',
forceValue: ForceX<Node> | ForceY<Node> | ForceManyBody<Node> | ForceLink<Node, SimulationEdge> | ForceCollide<Node> | undefined,
edgeDistance?: number,
) {
if (simulation === null) {
Expand Down

0 comments on commit 892bafb

Please sign in to comment.