Open martinweihrauch opened 4 years ago
Hello!
I'm not sure I see the full picture here. Wouldn't such functionality require inverting transform?
I'd totally appreciate a quick demo to explore the functionality. Please keep in mind that this library supports both SVG/DOM transformations. Ideally graphics-specific code should live in a corresponding controller (e.g. svg controller, dom controller ).
Yes, I already realized that with inverse transform. I put it in the options, so that you can add a selector
Is this pull request still out there?
OK!!! So, there's a bug in the browsers. It only really seems to work for a line. Just tried it. Paths ... sort of.
Information about the bug was pointed out on a post on StackExchange.
The following presents us with a hack: https://muffinman.io/blog/svg-non-scaling-circle-and-rectangle/
What I have finally done. I am using Svelte so there is a shorthand that result in possibly clumsy update. But, it works well enough.
In another environment, the updates have to be figured out a little more carefully.
I have two groups in my SVG. One is the target of panzoom. Another is behind it. It translates its elements when panzoom emits pan and zoom events.
Here is the initialization:
let panzoomOptions = {
maxZoom: 5,
minZoom: 1,
initialZoom: 1,
zoomDoubleClickSpeed: 1,
transformOrigin: {x: 0, y: 0},
zoomSpeed: 0.25,
preserveAspecRatio: false,
scaleFactors: { x : 1.0, y : 0.0 }
};
let line_points = []
let info_points = []
let divider_starts = -36;
let division_width = 200
let point = { x : divider_starts, y : 0 }
let left_shift = divider_starts*division_width
let info_delta = 3
for ( let i = 0; i < 1000; i++ ) {
line_points.push({ x : (i*division_width + left_shift), y : 0, index : (divider_starts + i)})
info_points.push({ x : (i*division_width + left_shift), y : 0, index : (divider_starts + i)})
}
let original_info_points = info_points.map(p => {
return Object.assign({},p)
})
The HTML part is done in Svelte, which will pick up changes to SVG when the arrays are changed in the panzoom events.
<svg style="width:100%">
<!-- this is the draggable root -->
<g>
{#each info_points as point }
<text x='{point.x}' y='100' stroke='none' fill='rgb(80,200,90)'vector-effect="non-scaling-size" >{point.index}</text>
{/each}
</g>
<g bind:this={canvasElt} >
{#each line_points as point }
<line x1='{point.x}' x2='{point.x}' y1='0' y2='110' height='100' stroke-width="2" stroke="rgb(0,0,0)" vector-effect="non-scaling-stroke" />
{/each}
</g>
</svg>
Then, in the events, you have to make changes to info_points and track the state of the transform:
onMount(() => {
// panzoom
panzoomInstance = panzoom(canvasElt,panzoomOptions);
panzoomInstance.on('zoom', (e) => { /// left to right only
let tt = e.getTransform()
tt.y = 0 // this is the keeping vertical tick marks from floating up
let repoint = original_info_points.map(p => {
let oo = Object.assign({},p)
oo.x = oo.x*tt.scaleX + tt.x + (info_delta*tt.scaleX) // scale + offset + scaled delta
return oo
})
info_points = repoint
});
panzoomInstance.on('zoomend', (e) => { /// left to right only
let tt = e.getTransform()
tt.y = 0
let repoint = original_info_points.map(p => {
let oo = Object.assign({},p)
oo.x = oo.x*tt.scaleX + tt.x + (info_delta*tt.scaleX) // scale + offset + scaled delta
return oo
})
info_points = repoint
});
panzoomInstance.on('pan', (e) => { /// left to right only
let tt = e.getTransform()
tt.y = 0
let repoint = original_info_points.map(p => {
let oo = Object.assign({},p)
oo.x = oo.x*tt.scaleX + tt.x + (info_delta*tt.scaleX) // scale + offset + scaled delta
return oo
})
info_points = repoint
});
})
The labels by the tick marks drift when the smooth transition is going. But, they settle smoothly back into place.
Similar means can be programmed for vertical and radial changes. An idea might be to do fixed concentric circles with the panzoom centered at their center.
Hi! Thanks for that excellent library! I want to add the functionality for adding annotations. These "pins" should not "grow", when an image is zoomed. I would code something that you can exclude elements from getting larger (by reverse transforming). Do you want to implement that yourself or do you want me to implement and add a pull request? I would think that you can add a selector to the options (like "exclude all #divContainer .noZoom").