dicom-microscopy-viewer
Version:
Interactive web-based viewer for DICOM Microscopy Images
183 lines (163 loc) • 5.22 kB
JavaScript
import Style from 'ol/style/Style'
import Stroke from 'ol/style/Stroke'
import Point from 'ol/geom/Point'
import LineString from 'ol/geom/LineString'
import Icon from 'ol/style/Icon'
import Enums from '../../enums'
import defaultStyles from '../styles'
/**
* Format arrow output.
*
* @param {LineString} arrow geometry
*
* @return {string} The formatted output
*
* @private
*/
export const _format = (feature) =>
feature.get(Enums.InternalProperties.Label) || ''
/**
* Build arrow styles.
*
* @param {object} feature The feature instance
* @param {object} map The viewer map instance
*
* @returns {object} Style instance
*
* @private
*/
const _applyStyles = (feature, map) => {
const geometry = feature.getGeometry()
if (geometry instanceof Point || geometry instanceof LineString) {
const anchor = [0, 0.5]
const rotation = 120
const point = geometry.getCoordinates()
const styleOptions = feature.get(Enums.InternalProperties.StyleOptions)
const color =
styleOptions && styleOptions.stroke && styleOptions.stroke.color
? styleOptions.stroke.color
: defaultStyles.stroke.color
feature.setStyle((feature, resolution) => {
const view = map.getView()
const currentZoomLevel = view.getZoom()
const zoomResolution = view.getResolutionForZoom(currentZoomLevel)
const newScale = zoomResolution / resolution
const pointIcon = `
<svg version="1.1" width="70px" height="70px" viewBox="0 -7.101 760.428 415.101" style="enable-background:new 0 0 408 408;" xmlns="http://www.w3.org/2000/svg">
<g>
<path style="fill:${encodeURIComponent(
color
)};" d="M 736.978 175.952 L 96.9 178.5 L 239.7 35.7 L 204 0 L 0 204 L 204 408 L 239.7 372.3 L 96.9 229.5 L 737.197 224.191 L 736.978 175.952 Z"/>
</g>
</svg>
`
const icon = `
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="70px" height="70px" viewBox="0 0 407.436 407.436" style="enable-background:new 0 0 407.436 407.436;">
<polygon style="fill:${encodeURIComponent(
color
)};" points="315.869,21.178 294.621,0 91.566,203.718 294.621,407.436 315.869,386.258 133.924,203.718 "/>
</svg>
`
const styles = []
if (geometry instanceof LineString) {
geometry.forEachSegment((start, end) => {
const dx = end[0] - start[0]
const dy = end[1] - start[1]
const rotation = Math.atan2(dy, dx)
const arrowStyle = new Style({
geometry: new Point(start),
image: new Icon({
opacity: 1,
src: `data:image/svg+xml;utf8,${icon}`,
scale: newScale /** Absolute-sized icon */,
anchor: [0.3, 0.5],
rotateWithView: true,
rotation: -rotation
})
})
styles.push(
new Style({
stroke: new Stroke({
color,
width: 5 * newScale /** Keep scale sync with icon */
})
})
)
/** Arrow */
styles.push(arrowStyle)
})
return styles
}
const iconStyle = new Style({
geometry: new Point(point),
image: new Icon({
opacity: 1,
src: `data:image/svg+xml;utf8,${pointIcon}`,
scale: newScale /** Absolute-sized icon */,
anchor,
rotateWithView: true,
rotation: -rotation
})
})
return iconStyle
})
}
}
const _isArrow = (feature) =>
Enums.Marker.Arrow === feature.get(Enums.InternalProperties.Marker)
/**
* Arrow marker.
*
* @param {object} dependencies Shared dependencies
* @param {object} dependencies.map Map shared instance
* @param {object} dependencies.markupManager Markup manager shared instance
*
* @class
* @private
*/
const ArrowMarker = ({ map, markupManager }) => {
return {
onAdd: (feature) => {
if (_isArrow(feature)) {
_applyStyles(feature, map)
/** Keep arrow style after external style changes */
feature.on(
Enums.FeatureEvents.PROPERTY_CHANGE,
({ key: property, target: feature }) => {
if (property === Enums.InternalProperties.StyleOptions) {
_applyStyles(feature, map)
}
}
)
/** Update arrow icon position on feature geometry change */
feature.getGeometry().on(Enums._FeatureGeometryEvents.CHANGE, () => {
_applyStyles(feature, map)
})
}
},
onDrawStart: ({ feature }) => {
if (_isArrow(feature)) {
_applyStyles(feature, map)
}
},
onRemove: (feature) => {
if (_isArrow(feature)) {
const featureId = feature.getId()
markupManager.remove(featureId)
}
},
onFailure: (uid) => {
if (uid) {
markupManager.remove(uid)
}
},
onUpdate: (feature) => {
if (_isArrow(feature)) {
_applyStyles(feature, map)
}
},
onDrawEnd: ({ feature }) => {},
onDrawAbort: ({ feature }) => {}
}
}
export default ArrowMarker