How can I use a hatch fill for annotations in WebViewer?

Hi @Matt_Parizeau ,
I implemented as you have suggested, we are facing 3 issues.

1 ) Page unresponsive / page become slow :

  • as you mentioned, pre-filled hatch annotation(already hatch) can be load on the time of Webviewer instance, see my below code, It’s causing page unresponsiveness / page loads much (because of constantly executing of setCustomHandler()).
  • this loadHatchAnnotation() method, I’ve called after instance loaded.
    image

result :
image

2 ) updating one type of annotation, affects same type of another annotation :
here I am sharing code snippet, for hatching. If I am changing one Ellipse, then the changes affects to another Ellipse which I’ve already hatched with different styles.

const { Core } = instance;	
const annotList = Core.annotationManager.getSelectedAnnotations();	
annotList.forEach(annotation => {	
         annotation.setCustomData('customFillStyle', 'hatch');	
         this.fillHatching(instance,annotation,optionValue); //optionValue will be : Solid Fill / Hatch - Fine / Hatch - Coarse
});	

=====================================
//this method we are
fillHatching(instance, selectedAnnotation:any, value:any){	
        const { Core } = instance;	
        let originalColors:any = JSON.parse(localStorage.getItem('originalColors'));	
        if(originalColors)	
        {	
            const dataAvailable = originalColors.filter(element => element.annotationID == selectedAnnotation.id);	
            const indexOfObject = this.allVersions.indexOf(dataAvailable);	
            originalColors.splice(indexOfObject,1);	
        }	
        else{	
            originalColors = [];	
        }	
        let formValue = {	
            strokeInString:selectedAnnotation.StrokeColor.toString(),	
            fillInString:selectedAnnotation.FillColor.toString(),	
            StrokeThickness:selectedAnnotation.StrokeThickness.toString()	
        };	
        let newObj={	
            annotationID : selectedAnnotation.Id,	
            annotationValues : formValue	
        }	
                	
        originalColors.push(newObj);	
        selectedAnnotation.setCustomData('originalColors', JSON.stringify(originalColors));	
        localStorage.setItem('originalColors', JSON.stringify(originalColors))	
        	
        let annotationType:any;	
        if(selectedAnnotation.Subject == 'Ellipse'){	
            annotationType = Core.Annotations.EllipseAnnotation;	
        }	
        else if(selectedAnnotation.Subject == 'Rectangle'){	
            annotationType = Core.Annotations.RectangleAnnotation;	
        }	
        else if(selectedAnnotation.Subject == 'Polygon'){	
            annotationType = Core.Annotations.PolygonAnnotation;	
        }	
        switch (value) {	
            case "Solid Fill":	
                selectedAnnotation.deleteCustomData('customFillStyle');	
                Core.annotationManager.redrawAnnotation(selectedAnnotation);	
                Core.annotationManager.trigger('annotationChanged', [[selectedAnnotation], 'modify', {}]);	
                break;	
            case "Hatch - Fine":	
            case "Hatch - Coarse" :	
                Core.Annotations.setCustomDrawHandler(annotationType, (ctx, pageMatrix, rotation, options) => {	
                    const { annotation, originalDraw } = options;	
                    // && selectedAnnotation.Id !== annotation.Id
                    if (annotation.getCustomData('customFillStyle') !== 'hatch') {	
                        // you can use this block if you want non-measurement ellipses to not have a hatch fill	
                        originalDraw(ctx, pageMatrix);	
                        return;	
                    }	
                    const hatchSize = (value == "Hatch - Fine") ? 10 : (value == "Hatch - Coarse" ? 16 : 0);	
                    selectedAnnotation.setCustomData('hatchSize', hatchSize.toString());
                    
                    if(annotation.Subject == 'Ellipse')	
                    {	
                        ctx.beginPath();	
                        annotation.setStyles(ctx, pageMatrix);	
                        
                        const x = annotation.X + annotation.fringe.x1;	
                        const y = annotation.Y + annotation.fringe.y1;	
                        let width = annotation.getWidth() - annotation.fringe.x1 - annotation.fringe.x2;	
                        let height = annotation.getHeight() - annotation.fringe.y1 - annotation.fringe.y2;	
                        
                        width = Math.max(width, 1);	
                        height = Math.max(height, 1);	
                        
                        // cap the linewidth if it is higher than the width or height	
                        const minDimension = Math.min(width, height);	
                        if (ctx.lineWidth >= minDimension) {	
                        ctx.lineWidth = Math.max(minDimension - 1, 1);	
                        }	
                        
                        ctx.lineWidth *= 2;	
                        
                        const whRatio = width / height;	
                        if (isNaN(whRatio) || whRatio === Infinity) {	
                        return;	
                        }	
                        ctx.save();	
                        // move annotation to (width / 2, 0), the center top point to start drawing the circle	
                        ctx.translate(x + (1 - whRatio) * width / 2, y);	
                        // scale the cirle to become an ellipse	
                        ctx.scale(whRatio, 1);	
                        
                        ctx.beginPath();	
                        // center-x, center-y, radius, start-angle, end-angle, ccw	
                        ctx.arc(width * 0.5, height * 0.5, Math.max(height * 0.5, 0), 0, Math.PI * 2, false);	
                        ctx.closePath();	
                        ctx.restore();	
                        ctx.clip();	
                        
                        ctx.stroke();	
                        
                        // uncomment the next line if you want the hatch line color to be the "FillColor" of the annotation	
                        ctx.strokeStyle = ctx.fillStyle;	
                        
                        // const hatchLineWidth = 1;	
                        ctx.lineWidth = annotation.StrokeThickness;	
                    }	
                    else if(annotation.Subject == 'Rectangle'){	
                        ctx.beginPath();	
                        annotation.setStyles(ctx, pageMatrix);	
                        
                        let width = annotation.getWidth() - annotation.fringe.x1 - annotation.fringe.x2;	
                        let height = annotation.getHeight() - annotation.fringe.y1 - annotation.fringe.y2;	
                        
                        width = Math.max(width, 1);	
                        height = Math.max(height, 1);	
                        
                        // cap the linewidth if it is higher than the width or height	
                        const minDimension = Math.min(width, height);	
                        if (ctx.lineWidth >= minDimension) {	
                        ctx.lineWidth = Math.max(minDimension - 1, 1);	
                        }	
                        
                        ctx.lineWidth *= 2;	
                        
                        const whRatio = width / height;	
                        if (isNaN(whRatio) || whRatio === Infinity) {	
                        return;	
                        }	
                        ctx.save();	
                        ctx.beginPath();	
                        ctx.rect(annotation.X, annotation.Y, annotation.getWidth(), annotation.getHeight());	
                        ctx.closePath();	
                        ctx.restore();	
                        ctx.clip();	
                        
                        ctx.stroke();	
                        
                        // uncomment the next line if you want the hatch line color to be the "FillColor" of the annotation	
                        ctx.strokeStyle = ctx.fillStyle;	
                    
                        // const hatchLineWidth = 1;	
                        ctx.lineWidth = annotation.StrokeThickness;	
                    }	
                    else if(annotation.Subject == 'Polygon'){	
                                                        
                        annotation.setStyles(ctx, pageMatrix);	
                        
                        // uncomment the next line if you want the hatch line color to be the "FillColor" of the annotation	
                        ctx.strokeStyle = ctx.fillStyle;
                        ctx.lineWidth = annotation.StrokeThickness;	
                            
                        let polygon = annotation.getPath();
                        ctx.beginPath();
                        ctx.moveTo(polygon[0].X, polygon[0].Y);

                        for(let item = 1; item < polygon.length; item++ ){
                            ctx.lineTo( polygon[item].X , polygon[item].Y )
                        }

                        ctx.closePath();
                        ctx.stroke();
                    }
                    
                    // vertical lines	
                    for (let i = annotation.X-100; i < annotation.X + annotation.Width+200; i += hatchSize) {	
                        ctx.beginPath();	
                        ctx.moveTo(i+140, annotation.Y-120);	
                        ctx.lineTo(i-230, annotation.Y + annotation.Height+250);	
                        ctx.stroke();	
                    }  	
                });	
                	
                Core.annotationManager.redrawAnnotation(selectedAnnotation);	
                Core.annotationManager.trigger('annotationChanged', [[selectedAnnotation], 'modify', {}]);	
                  	
                break;
                	
            default:	
                break;
        }
    }

result :
Annotaion

3 ) Polygon Annotation not being drawn :

  • as I shared above code snippet, you can see, I’ve used same logic for Polygon type annotations, but still its not working.
    result :
    Polygon Annotaion