diff --git a/cypress/integration/rendering/imageShape.spec.ts b/cypress/integration/rendering/imageShape.spec.ts index 4ae4326ea..228ca5d4e 100644 --- a/cypress/integration/rendering/imageShape.spec.ts +++ b/cypress/integration/rendering/imageShape.spec.ts @@ -1,7 +1,7 @@ import { imgSnapshotTest } from '../../helpers/util'; const looks = ['classic', 'handDrawn'] as const; -const directions = ['TB', 'BT', 'LR', 'RL'] as const; +const directions = ['TB', 'LR'] as const; const labelPos = [undefined, 't', 'b'] as const; looks.forEach((look) => { @@ -18,7 +18,7 @@ looks.forEach((look) => { let flowchartCode = `flowchart ${direction}\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`; - flowchartCode += `, w: '200', h: '200'`; + flowchartCode += `, w: '100', h: '200'`; if (pos) { flowchartCode += `, pos: '${pos}'`; } @@ -30,7 +30,7 @@ looks.forEach((look) => { let flowchartCode = `flowchart ${direction}\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`; - flowchartCode += `, w: '100', h: '100'`; + flowchartCode += `, w: '100', h: '250'`; if (pos) { flowchartCode += `, pos: '${pos}'`; } @@ -42,17 +42,18 @@ looks.forEach((look) => { let flowchartCode = `flowchart ${direction}\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; - flowchartCode += `, w: '450', h: '550'`; + flowchartCode += `, w: '550', h: '200'`; if (pos) { flowchartCode += `, pos: '${pos}'`; } flowchartCode += ` }@\n`; - imgSnapshotTest(flowchartCode, { look }); + imgSnapshotTest(flowchartCode, { look, htmlLabels: true }); }); it(`with markdown htmlLabels:false`, () => { let flowchartCode = `flowchart ${direction}\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; + flowchartCode += `, w: '250', h: '200'`; if (pos) { flowchartCode += `, pos: '${pos}'`; @@ -68,6 +69,7 @@ looks.forEach((look) => { it(`with styles`, () => { let flowchartCode = `flowchart ${direction}\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + flowchartCode += `, w: '550', h: '200'`; if (pos) { flowchartCode += `, pos: '${pos}'`; @@ -79,10 +81,10 @@ looks.forEach((look) => { it(`with classDef`, () => { let flowchartCode = `flowchart ${direction}\n`; - flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`; flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; - flowchartCode += `, w: '450', h: '550'`; + flowchartCode += `, w: '500', h: '550'`; if (pos) { flowchartCode += `, pos: '${pos}'`; } diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts index aa9ac4896..21f185487 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts @@ -6,12 +6,11 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; import { createPathFromPoints } from './util.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; export const imageSquare = async (parent: SVG, node: Node) => { const { labelStyles, nodeStyles } = styles2String(node); node.labelStyle = labelStyles; - const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); - const { cssStyles } = node; const img = new Image(); img.src = node?.img ?? ''; @@ -22,15 +21,22 @@ export const imageSquare = async (parent: SVG, node: Node) => { const imageWidth = node?.assetWidth ?? imageNaturalWidth; const imageHeight = node?.assetHeight ?? imageNaturalHeight; + const defaultWidth = getConfig().flowchart?.wrappingWidth; + // const htmlLabels = getConfig().flowchart?.htmlLabels + + node.width = Math.max(node.width ?? 0, node.label ? (defaultWidth ?? 0) : 0, imageWidth); + + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + + const { cssStyles } = node; + const defaultHeight = bbox.height; + node.height = Math.max(node.height ?? 0, node.label ? (defaultHeight ?? 0) : 0, imageHeight); const width = Math.max(bbox.width + (node.padding ?? 0), imageWidth, node?.width ?? 0); const height = Math.max(bbox.height + (node.padding ?? 0), imageHeight, node?.height ?? 0); - // const imageSizeWidth = width / 2; - const imageSizeHeight = height * 0.1; - - const skeletonWidth = width + (node?.padding ?? 0); - const skeletonHeight = height + imageSizeHeight + bbox.height; + const skeletonWidth = width + (node?.padding ?? 0) / 2; + const skeletonHeight = height + bbox.height; const imagePosition = node?.pos ?? 'b'; const points = [ @@ -52,31 +58,32 @@ export const imageSquare = async (parent: SVG, node: Node) => { const linePath = createPathFromPoints(points); const lineNode = rc.path(linePath, options); - const iconShape = shapeSvg.insert(() => lineNode, ':first-child'); + const imageShape = shapeSvg.insert(() => lineNode, ':first-child').attr('opacity', 0); if (node.img) { const image = shapeSvg.append('image'); // Set the image attributes image.attr('href', node.img); - image.attr('width', imageWidth); - image.attr('height', imageHeight); + image.attr('width', node.width); + image.attr('height', node.height); + image.attr('preserveAspectRatio', 'none'); const yPos = imagePosition === 'b' - ? -(skeletonHeight / 2 - imageSizeHeight / 2) - : skeletonHeight / 2 - height - imageSizeHeight / 2; - image.attr('transform', `translate(${-imageWidth / 2}, ${yPos})`); + ? -(skeletonHeight / 2) + : skeletonHeight / 2 - height + (bbox.y + (bbox.top ?? 0)) * 2; + image.attr('transform', `translate(${-node.width / 2}, ${yPos})`); } if (cssStyles && node.look !== 'handDrawn') { - iconShape.selectAll('path').attr('style', cssStyles); + imageShape.selectAll('path').attr('style', cssStyles); } if (nodeStyles && node.look !== 'handDrawn') { - iconShape.selectAll('path').attr('style', nodeStyles); + imageShape.selectAll('path').attr('style', nodeStyles); } - iconShape.attr('transform', `translate(${-skeletonWidth / 2},${-skeletonHeight / 2})`); + imageShape.attr('transform', `translate(${-skeletonWidth / 2},${-skeletonHeight / 2})`); const yPos = imagePosition === 'b' @@ -85,7 +92,7 @@ export const imageSquare = async (parent: SVG, node: Node) => { label.attr('transform', `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${yPos})`); - updateNodeBounds(node, iconShape); + updateNodeBounds(node, imageShape); node.intersect = function (point) { log.info('iconSquare intersect', node, point);