I saw an example of "Render geometries to a canvas":
var canvas = document.getElementById('canvas');
var vectorContext = ol.render.toContext(canvas.getContext('2d'), {size: [100, 100]});
var fill = new ol.style.Fill({color: 'blue'});
var stroke = new ol.style.Stroke({color: 'black'});
var style = new ol.style.Style({
fill: fill,
stroke: stroke,
image: new ol.style.Circle({
radius: 10,
fill: fill,
stroke: stroke
})
});
vectorContext.setStyle(style);
vectorContext.drawGeometry(new ol.geom.LineString([[10, 10], [90, 90]]));
vectorContext.drawGeometry(new ol.geom.Polygon([[[2, 2], [98, 2], [2, 98], [2, 2]]]));
vectorContext.drawGeometry(new ol.geom.Point([88, 88]));
But what to do with the geometry in the projection EPSG:4326 (or EPSG:3857)?
PS
I saw the question "How can we render an OpenLayers 3 feature to a canvas using a style but not using a map", but I don't understand what projection the code works with. And to clarify the author does not allow me to low reputation on stackoverflow.
The HTML canvas element is used to draw graphics, on the fly, via JavaScript.
If your drawing in a canvas there is no more projection anymore, you're in pixel coordinate. You'll have to transform your geometry in pixel.
See the map's getPixelFromCoordinate function if you're drawing in the map canvas.
#Catch I dug in a little. In that answer he uses canvas.width (in pixels) and ol.extent.getWidth(extent) /height. ol.Extent is only array of numbers and don't have any information about coordinate system. If you would use geographic coordinates it would work with them like they are carthesian. So it depends on what area you want to diplay, but I would recomend to tranform it to some projection and then use the advised approach - translate, scale, translate (scale is now supported in ol.geom).
I was able to draw a polygon on canvas:
var geoJson = '{"type":"Polygon","coordinates":[[[32.00592041015625,49.55951603052614],[31.97296142578125,49.51673910294474],[32.103424072265625,49.433752230525585],[32.224273681640625,49.346151509388676],[32.54974365234375,49.24718981286537],[32.81890869140625,49.09814978542761],[32.80517578125,49.0729662700941],[32.85736083984375,49.0657686340536],[32.87933349609375,49.08376076915357],[32.95623779296875,49.067568140816434],[32.98370361328125,49.09095579858044],[33.145751953125,49.081961848889364],[33.11828613281251,49.067568140816434],[33.123779296875,49.056770122686174],[33.24737548828125,49.063969062121345],[33.23089599609375,49.16284875720291],[33.12652587890625,49.18080571099239],[33.079833984375,49.256153800301064],[32.95898437500001,49.28841067865025],[32.87933349609375,49.3295971091282],[32.83538818359375,49.38863055043896],[32.8436279296875,49.42794681507826],[32.67608642578125,49.4672315972079],[32.67333984375001,49.4297331699307],[32.7447509765625,49.352413884497594],[32.66510009765625,49.34794084076262],[32.52227783203125,49.38460779401288],[32.31079101562501,49.513172668717914],[32.18856811523438,49.50247180563116],[32.18856811523438,49.50247180563116],[32.00592041015625,49.55951603052614]]]}';
var parser = new ol.format.GeoJSON();
var feature = parser.readFeature( geoJson );
var geom = feature.getGeometry();
var canvas = document.getElementById( 'canvas' );
var fill = new ol.style.Fill({ color: 'blue' });
var stroke = new ol.style.Stroke({ color: 'black' });
var style = new ol.style.Style({
fill : fill,
stroke: stroke,
image : new ol.style.Circle({
radius: 10,
fill : fill,
stroke: stroke
})
});
function render( height, width, canvas, geometry, style ) {
var vectorContext = ol.render.toContext(
canvas.getContext( '2d' ),
{ size: [width, height] }
);
var geom = geometry.clone(),
line = geom.getCoordinates()[0],
extent = ol.extent.boundingExtent( line );
var dxy = ol.extent.getCenter(extent),
sxy = [
width / ol.extent.getWidth(extent),
height / ol.extent.getHeight(extent)
];
var dx = dxy[0],
dy = dxy[1],
sx = sxy[0],
sy = sxy[1];
geom.translate( -dx, -dy );
geom.scale( Math.min(sx, sy), -Math.min(sx, sy) );
geom.translate( width / 2, height / 2 );
vectorContext.setStyle( style );
vectorContext.drawGeometry( geom );
}
geom.transform( 'EPSG:4326', 'EPSG:3857' );
render( 400, 400, canvas, geom, style );
<script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
<canvas id="canvas" width="400" height="400" style="width: 400px; height: 400px;"></canvas>
Example:
OpenLayers rendering Geometry to Canvas
I have a simple rectangle that forms the clipping area for all shapes added to the canvas, which is working great:
var area = new paper.Rectangle(
100, 100, 300, 120
);
var path = new paper.Path.Rectangle(area);
group.addChild(path);
group.clipped = true;
What I'm trying to achieve is instead of hiding the paths that fall outside of this area, they are shown with a slight opacity, something like:
Thanks in advance for any help and suggestions.
This is not a simple way as clipped, you might do it by using method intersect.
Please try this code.
// SET INITIAL
var area = new paper.Path.Rectangle(100, 100, 300, 220);
area.fillColor = 'yellow'
area.opacity = 0.2
var circle1 = new paper.Path.Circle({
center:[150, 150],
radius: 100,
fillColor: 'red'
})
// OPACITY CLIPPING
var circle2 = circle1.intersect(area)
circle1.opacity = 0.2
I have this circle object:
function makeCircle(left, top, line1, line2, lineId, stationIndex, stationID) {
var c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 0.2,
radius: 1.5,
fill: '#ffffff',
stroke: '#666',
// isMoving: false,
selectable: true,
});
c.hasControls = c.hasBorders = true;
c.stationID = stationID;
c.stationIndex = stationIndex;
c.line1 = line1;
c.line2 = line2;
return c;
}
I run in a loop , and insert some circles to a group by id of a line.
(every line has id ) :
circleGroup[lineId] = new fabric.Group([],{selectable: false,});
var circle = makeCircle(x, y, null, line, lineId, 0, circle1Id);
circleGroup[lineId].add(circle);
I want when click on edit() function, the circles in circleGroup[lineId] (lineId = 10120 for exemple ) can be selectable.
function edit(lineId) {
circleGroup[lineId].selectable = true;
canvas.renderAll();
}
But not happen nothing. the circles not moving when I click on them and try to move.
what the problem?
I'm not quite sure what you're after. Do you want the circles to become selectable/interactive, or do you want the circle groups to be selectable/interactive?
It looks like your edit function is making the circleGroup[lineID] selectable. Your code above doesn't show the circleGroup being made un-selectable.
If what you want is to make each of the objects in the circleGroup selectable. Try:
function edit(lineId) {
var group = circleGroup[lineId]
for (var i=0; i<group._objects.length; i++){
group._objects[i].selectable = true;
}
canvas.renderAll();
}
Note that when you click on one of your circles it will still be inside a group, so any interaction with the selection (drag, scale, rotate, etc) will be applied to the group.
If you want to make each circle interactive, you'll need to ungroup them first. Try following this: Grouping and Ungrouping Fabric.js objects
I would like to draw a circle on a scatter plot to highlight values outside of the acceptable range.
I tried to use chart.renderer.circle but that uses the x and y pixels of the SVG element. I still want to be able to zoom in or out, so absolute x and y values don't work.
Is this possible with Highchart?
Edit:
Added Mockup:
Two ideas...
ONE
Use chart.renderer.circle and translate the point values to pixels.
Say you want to draw a circle at:
var circleX = 161.2; // x coordinate
var circleY = 51.6; // y coordinate
var circleR = 1.0; // radius size in terms of x axis distance
Draw the circle as:
function addCircle(chart){
if (this.circle){
// on a redraw, remove old circle
$(this.circle.element).remove();
}
// translate my coordinates to pixel values
var pixelX = chart.xAxis[0].toPixels(circleX);
var pixelY = chart.yAxis[0].toPixels(circleY);
var pixelR = chart.xAxis[0].toPixels(circleR) - chart.xAxis[0].toPixels(0);
// add my circle
this.circle = chart.renderer.circle(pixelX, pixelY, pixelR).attr({
fill: 'transparent',
stroke: 'black',
'stroke-width': 1
});
this.circle.add();
}
You then call this in the load and redraw events and all is awesome:
events: {
load: function(){
addCircle(this);
},
redraw: function(){
addCircle(this);
}
}
Here's a fiddle example.
TWO
Add the circle as another series, make the marker a giant transparent circle:
{
data: [[circleX, circleY]],
linkedTo: 'other', // link it to other series to avoid legend entry
marker: {
radius: 40,
lineColor: 'red',
fillColor: 'transparent',
lineWidth: 1,
symbol: 'circle'
}
}
Here's a fiddle for this one.
I am creating a circle as a group of kinetic arcs. When I cache the group and subsequently call the draw function on the layer, three quarters of the circle are hidden. I think layer.draw may require an offset but really I'm only guessing. When I remove the fill, stroke or opacity from the arc or the object literal from the cache call then the full circle is displayed. http://jsfiddle.net/leydar/gm2FT/5/ Any insights gratefully received.
function createArc(n){
var arc = new Kinetic.Arc({
innerRadius: 30,
outerRadius: 50,
/* if I remove the fill, stroke or opacity
the full wheel is correctly displayed */
fill: 'blue',
stroke: 'black',
opacity: 0.3,
strokeWidth: 1,
angle: 36,
rotation: 36*n
});
return arc;
}
function init() {
var arc;
var stage = new Kinetic.Stage({
container: 'container',
width: 104,
height: 104
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Group();
for(var i=0;i<10;i++) {
arc = createArc(i);
circle.add(arc);
};
layer.add(circle);
stage.add(layer);
/* if I do not cache or do not call layer.draw()
then again the wheel is correctly displayed */
circle.cache({
x: -52,
y: -52,
width: 104,
height: 104,
drawBorder: true
});
layer.draw();
}
init();
Stephen
This is a bug of KineticJS.
You may use this workaround:
Kinetic.Arc.prototype._useBufferCanvas = function() {
return false;
};
http://jsfiddle.net/gm2FT/6/