Hi,
I have implemented a scalable annotation which will pann and zoom with a heatmap,
see code below,
class ScalableAnnotation extends CustomAnnotation {
constructor(...args) {
super(...args)
this.zoomFactor
this.initialWidth
this.initialHeight
this.initialDiff
this.initialCircleRadius
this.diff
}
update(xCalc, yCalc, xCoordSvgTrans, yCoordSvgTrans) {
super.update(xCalc, yCalc, xCoordSvgTrans, yCoordSvgTrans);
if (!this.initialDiff) {
this.initialDiff = xCalc.visibleMax - xCalc.visibleMin;
this.initialCircleRadius = Number.parseFloat(d3.select(this.svg).selectAll('circle').attr('r'))
this.initialCircleStrokeWidth = Number.parseFloat(d3.select(this.svg).selectAll('circle').style('stroke-width'))
this.initialLineStrokeWidth = Number.parseFloat(d3.select(this.svg).selectAll('polygon').style('stroke-width'))
this.initialWidth = Number.parseFloat(this.svg.getAttribute("width"));
this.initialHeight = Number.parseFloat(this.svg.getAttribute("height"));
this.zoomFactor = 1
} else {
this.diff = xCalc.visibleMax - xCalc.visibleMin;
if (this.diff !== this.initialDiff) {
this.zoomFactor = this.initialDiff / this.diff
const width = this.initialWidth * this.zoomFactor;
const height = this.initialHeight * this.zoomFactor;
d3.select(this.svg).selectAll('circle').attr('r', (this.initialCircleRadius / this.zoomFactor) + 0.01)
d3.select(this.svg).selectAll('circle').style('stroke-width', (this.initialCircleStrokeWidth / this.zoomFactor) + 0.003)
d3.select(this.svg).selectAll('polygon').style('stroke-width', (this.initialLineStrokeWidth / this.zoomFactor) + 0.01)
this.setSvgAttribute("width", width);
this.setSvgAttribute("height", height);
let borderX1 = this.getX1Coordinate(xCalc, yCalc) + this.xCoordShift;
let borderY1 = this.getY1Coordinate(xCalc, yCalc) + this.yCoordShift;
this.setAnnotationBorders(
borderX1,
borderX1 + width,
borderY1,
borderY1 + height
);
this.updateAdornerInner();
}
}
}
}
This works fantastic when zooming in and zooming out or panning see video below,
Bur when we resize the heatmap, the annotations do not scan with the heatmap. see video below,
Any suggestion on how to deal with this scenario?
Thanks,
Pramod
- pramod butte asked 8 months ago
- Hello, I guess we need a working example to check this. Could you provide one? And, are you able to reproduce the issues on the basic setup here: https://codepen.io/jim-risen/pen/LYoGwWX
- Actually disregard that. We see the issue now, and going to try making some improvementsto the ScalableAnnotation.
- You must login to post comments
Thank you! looking forward to the improvements.
Best,
Pramod
- pramod butte answered 8 months ago
- You must login to post comments
Here is an updated version of the ScalableAnnotation.
Please check and let us know if that works correctly.
class ScalableAnnotation extends CustomAnnotation {
private initialXDiff: number;
private initialYDiff: number;
public update(
xCalc: CoordinateCalculatorBase,
yCalc: CoordinateCalculatorBase,
xCoordSvgTrans: number,
yCoordSvgTrans: number
): void {
super.update(xCalc, yCalc, xCoordSvgTrans, yCoordSvgTrans);
const borders = this.getAnnotationBorders();
if (this.initialXDiff === undefined && this.initialYDiff === undefined) {
const initialX2 = this.getValue(borders.x2, xCalc, ECoordinateMode.Pixel);
const initialY2 = this.getValue(borders.y2, yCalc, ECoordinateMode.Pixel);
this.initialXDiff = initialX2 - this.x1;
this.initialYDiff = initialY2 - this.y1;
} else {
const actualX2 = this.getValue(borders.x2, xCalc, ECoordinateMode.Pixel);
const actualY2 = this.getValue(borders.y2, yCalc, ECoordinateMode.Pixel);
const currentXDiff = actualX2 - this.x1;
const currentYDiff = actualY2 - this.y1;
if (this.initialXDiff !== currentXDiff || this.initialYDiff !== currentYDiff) {
const x1Coordinate = this.getX1Coordinate(xCalc, yCalc);
const y1Coordinate = this.getY1Coordinate(xCalc, yCalc);
const x2Coordinate = this.getCoordinate(this.x1 + this.initialXDiff, xCalc, this.xCoordinateMode);
const y2Coordinate = this.getCoordinate(this.y1 + this.initialYDiff, yCalc, this.yCoordinateMode);
const width = Math.abs(x2Coordinate - x1Coordinate);
const height = Math.abs(y2Coordinate - y1Coordinate);
this.setSvgAttribute("width", width);
this.setSvgAttribute("height", height);
const borderX1 = x1Coordinate + this.xCoordShift;
const borderY1 = y1Coordinate + this.yCoordShift;
const borderX2 = borderX1 + width;
const borderY2 = borderY1 + height;
this.setAnnotationBorders(borderX1, borderX2, borderY1, borderY2);
this.updateAdornerInner();
}
}
}
}
Also you can check it here:
Example on CodePen
- Jim Risen answered 8 months ago
- You must login to post comments
apologies for late response… trying it now, I will get back to you shortly
Pramod
- pramod butte answered 8 months ago
- You must login to post comments
Dear Jim,
Although the suggested code works great. there is one major issue which I am unable to resolve. After the scalable annotation is initialized and when one zooms in the first time the size of the svg seem to jump. After which the svg scales normally. But due to that initial jump the registration to the heatmap is lost. please see the video below:
- pramod butte answered 7 months ago
- Hello, sorry, I’ve just noticed this. Let us know if you have managed to resolve the issue. Otherwise, please create a new thread here on Forum or via the Support Desk
- You must login to post comments
Please login first to submit.