src/shapes/segment.js
import BaseShape from './base-shape';
/**
* A shape to display a segment.
*
* [example usage](./examples/layer-segment.html)
*/
export default class Segment extends BaseShape {
getClassName() { return 'segment'; }
_getAccessorList() {
return { x: 0, y: 0, width: 0, height: 1, color: '#000000', opacity: 1 };
}
_getDefaults() {
return {
displayHandlers: true,
handlerWidth: 2,
handlerOpacity: 0.8,
opacity: 0.6
};
}
render(renderingContext) {
if (this.$el) { return this.$el; }
this.$segment = document.createElementNS(this.ns, 'rect');
this.$segment.classList.add('segment');
this.$segment.style.opacity = this.params.opacity;
this.$segment.setAttributeNS(null, 'shape-rendering', 'geometricPrecision');
const useShortcut = (this.getClassName() == 'segment' && // not a subclass
!this.params.displayHandlers);
if (useShortcut) {
this.$el = this.$segment;
} else {
this.$el = document.createElementNS(this.ns, 'g');
this.$el.appendChild(this.$segment);
if (this.params.displayHandlers) {
this.$leftHandler = document.createElementNS(this.ns, 'rect');
this.$leftHandler.classList.add('left', 'handler');
this.$leftHandler.setAttributeNS(null, 'width', this.params.handlerWidth);
this.$leftHandler.setAttributeNS(null, 'shape-rendering', 'crispEdges');
this.$leftHandler.style.opacity = this.params.handlerOpacity;
this.$leftHandler.style.cursor = 'ew-resize';
this.$rightHandler = document.createElementNS(this.ns, 'rect');
this.$rightHandler.classList.add('right', 'handler');
this.$rightHandler.setAttributeNS(null, 'width', this.params.handlerWidth);
this.$rightHandler.setAttributeNS(null, 'shape-rendering', 'crispEdges');
this.$rightHandler.style.opacity = this.params.handlerOpacity;
this.$rightHandler.style.cursor = 'ew-resize';
this.$el.appendChild(this.$leftHandler);
this.$el.appendChild(this.$rightHandler);
}
}
return this.$el;
}
update(renderingContext, datum) {
const x = renderingContext.timeToPixel(this.x(datum));
const y = renderingContext.valueToPixel(this.y(datum));
const width = renderingContext.timeToPixel(this.x(datum) +
this.width(datum)) - x;
const height = renderingContext.valueToPixel(this.height(datum));
this.$segment.setAttributeNS(null, 'x', x);
this.$segment.setAttributeNS(null, 'y', y);
this.$segment.setAttributeNS(null, 'width', Math.max(width, 0));
this.$segment.setAttributeNS(null, 'height', height);
const visible = (x + width >= renderingContext.minX &&
x <= renderingContext.maxX);
if (!visible) {
this.$el.setAttributeNS(null, 'visibility', 'hidden');
return;
} else {
this.$el.setAttributeNS(null, 'visibility', 'visible');
}
const color = this.color(datum);
const opacity = this.opacity(datum);
this.$el.style.opacity = opacity;
this.$segment.style.fill = color;
if (this.params.displayHandlers) {
this.$leftHandler.setAttributeNS(null, 'x', x);
this.$leftHandler.setAttributeNS(null, 'y', 0);
this.$leftHandler.setAttributeNS(null, 'height', height);
this.$leftHandler.style.fill = color;
this.$rightHandler.setAttributeNS(null, 'x',
x + width - this.params.handlerWidth);
this.$rightHandler.setAttributeNS(null, 'y', 0);
this.$rightHandler.setAttributeNS(null, 'height', height);
this.$rightHandler.style.fill = color;
}
}
inArea(renderingContext, datum, x1, y1, x2, y2) {
const shapeX1 = renderingContext.timeToPixel(this.x(datum));
const shapeX2 = renderingContext.timeToPixel(this.x(datum) + this.width(datum));
const shapeY1 = renderingContext.valueToPixel(this.y(datum));
const shapeY2 = renderingContext.valueToPixel(this.y(datum) + this.height(datum));
// http://jsfiddle.net/uthyZ/ - check overlaping area
const xOverlap = Math.max(0, Math.min(x2, shapeX2) - Math.max(x1, shapeX1));
const yOverlap = Math.max(0, Math.min(y2, shapeY2) - Math.max(y1, shapeY1));
const area = xOverlap * yOverlap;
return area > 0;
}
}