How can I change the blotter canvas size? - javascript

For some reason the blotter.js canvas size is not cangable. Blotter seems to generate a canvas named b-canvas by default? But I can't find where it gets it width and height from? And I am not able to set a new width and size by .style in js. Help?!
I've tried all the techniques I could find.
I've also tried to set a Overflow: visible to the parent (Text) in js and in the css file, but the render is still crashing with the bounds of the canvas. What am I doing wrong?
var text = new Blotter.Text("Hello", {
weight: 800,
size: 80,
fill: 'lightgray',
paddingLeft: 80,
paddingRight: 80,
paddingBottom: 80,
paddingTop: 80
});
/*
* https://blotter.js.org
*/
var blotter = new Blotter(material, {
texts: text
});
var canvas = blotter.forText(text).domElement;
canvas.style.visibility = 'visible!important';
canvas.style = "width: 100vh !important";
canvas.style = "height: 100vw !important";
canvas.style = "z-index: -3 !important";
container.appendChild(canvas);

You can simply wrap it inside a div and resize that. The canvas size is probably calculated based on the font-size and it is as big as the drawing itself.
<div id="wrap">
<canvas></canvas>
</div>
<style>
#wrap canvas {
width: 50px !important
}
</style>
Take a look at the "Blotter.js" website itself and inspect its logo, see that it has this same code and how you can resize it.

Related

Scale down a Konvajs stage without losing quality

Consider having a large (2000x1000) stage with some text in it. The stage gets downscaled to 1000x500 making the text unreadable. Then we try to enlarge the text by zooming it in.
Expected: the text should become readable again at some point.
Actual: the text remains unreadable (blurred) no matter how much we zoom in.
Try zooming the page in (with native browser zoom on desktop) after running the snippet:
const stage = new Konva.Stage({
container: 'container',
width: 2000,
height: 1000,
});
const layer = new Konva.Layer();
stage.add(layer);
const rect = new Konva.Text({
x : 50, y : 50, width: 100, height: 100,
fontSize: 12,
text: "This text should be readable when the viewport gets downscaled"
});
layer.add(rect).draw();
stage.scale({x: 0.5, y: 0.5});
stage.setAttrs({width: 1000, height: 500});
stage.draw();
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.js"></script>
<div id="container"></div>
The quality loss can be avoided by downscaling with CSS only, like this:
const stage = new Konva.Stage({
container: 'container',
width: 2000,
height: 1000,
});
const layer = new Konva.Layer();
stage.add(layer);
const rect = new Konva.Text({
x : 50, y : 50, width: 100, height: 100,
fontSize: 12,
text: "This text should be readable when the viewport gets downscaled"
});
layer.add(rect).draw();
stage.getChildren().forEach(function(layer) {
layer.canvas._canvas.style.width = "1000px";
layer.canvas._canvas.style.height = "500px";
layer.hitCanvas.setSize(1000, 500);
layer.hitCanvas.context.scale(0.5, 0.5);
});
stage.draw();
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.js"></script>
<div id="container"></div>
Note how text becomes readable at a certain level of zooming.
The workaround breaks Konvajs abstraction. What problems it can potentially cause? Is there a better way, which uses only public methods exposed by Konvajs?
In fabric.js it can be done like this (complete example here):
canvas.setDimensions({width: '1000px', height: '500px'}, {cssOnly: true});
Konva is a canvas framework. Canvas is a bitmap image unlike vector elements like SVG. So that "blur" should be expected. Technically to fix the issue you can redraw stage with higher pixelRatio on zoom event:
Konva.pixelRatio = 4
stage.draw();
That code will generate more pixels for canvas element. But the page may be very heavy in RAM in this case because Konva will have to produce very large canvas. In most of the mobile apps, you don't need native zooming and you can use responsive design. For zooming the stage, you can use Konva methods.

How to keep a view the same size in React Native when display size changes?

Our app includes a screen where there is a large circle in the background which changes position. It's mostly absolute positioning using this sort of style. The circle changes to use the right style and animates into the new position underneath some tutorial text.
const { height, width } = Dimensions.get('screen')
const circleRadius = isIphoneX() ? height * 0.55 : height * 0.60
export const styles = StyleSheet.create({
circleMassiveLeft: {
position: 'absolute',
backgroundColor: primary,
width: circleRadius * 2,
height: circleRadius * 2,
borderRadius: circleRadius,
left: -circleRadius + width - 50,
top: -circleRadius + height / 2
},
circleMassiveRight: {
position: 'absolute',
backgroundColor: primary,
width: circleRadius * 2,
height: circleRadius * 2,
borderRadius: circleRadius,
left: -circleRadius + 50,
top: -circleRadius + height / 2
}
})
This has been working great to display the circle in the correct position across multiple display sizes. Since it needs to be so precisely positioned, using absolute positioning seems to be a better solution than flex in this case. Our challenge is that when changing the system settings in Android to display size small, the circle becomes smaller. Of course, that makes sense in a way, but this particular element looks pretty awful because of the layout of the rest of the screen when it's resized to be smaller. Elements that used to be on top of it are now poking out! Is there a way to make sure that this element displays at the same size regardless of Android system display size settings? Poking around the docs, there doesn't seem to be a basic setting for this.
Try to use www.npmjs.com/package/react-native-responsive-dimensions
read this
In the article they using: react-native-size-matters

Fabricjs Textbox make the text shrink to fit

I would define a text box (single-line)
By default, with a character size of 16 (for example)
When the text gets bigger than the text box, I do not want it to wrap or the text box gets bigger, I want the text size to fit the maximum size of the text box. text. When the text returns to a smaller size, it can resume its initial size (in our example 16). Possibly manage a minimum size
If you have an idea, I take :)
thanks in advance
Test Case : http://jsfiddle.net/Da7SP/273/
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
// ADD YOUR CODE HERE
var canvas = window._canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('My Text', {
width: 200,
top: 5,
left: 5,
fontSize: 16,
textAlign: 'center'
});
var t2 = new fabric.Textbox('My text is longer, but I do not want the box to grow, or the text to wrap. I only want the text to fit the available size', {
width: 200,
height: 200,
top: 250,
left: 5,
fontSize: 16,
textAlign: 'center'
});
canvas.add(t1);
canvas.add(t2);
A small video to explain what I want :
When the text gets bigger than the text box, I want the text size fit the maximum size of the text box.
This is a basic fiddle that can replicate your idea.
The point is that you have an event that fires on every text change and that can be used to do something before the textbox is rendered.
In this case i m shrinking font size based on a non standard parameter i added to textbox called fixedWidth
// ADD YOUR CODE HERE
var canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('MyText', {
width: 150,
top: 5,
left: 5,
fontSize: 16,
textAlign: 'center',
fixedWidth: 150
});
canvas.on('text:changed', function(opt) {
var t1 = opt.target;
if (t1.width > t1.fixedWidth) {
t1.fontSize *= t1.fixedWidth / (t1.width + 1);
t1.width = t1.fixedWidth;
}
});
canvas.add(t1);
canvas {
border: 1px solid #999;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>
Here's a similar answer to https://stackoverflow.com/a/41335051/1469525 but this example modifies the fontSize up to a maxFontSize (the initial fontSize). This allows the text to shrink and then grow back to the original size, as well as preventing line wraps.
(Note, if you use this, you'll have to find a way to prevent the user from using the enter key. I put in a check that basically cancels it if an enter key is detected. My app actually has a separate form to enter the text, so I can control prevention through normal javascript. I'm not quite sure how to do that directly on a canvas element when it is editable like here...)
var canvas = new fabric.Canvas('c');
var t1 = new fabric.Textbox('MyText', {
width: 150,
top: 5,
left: 5,
fontSize: 16,
textAlign: 'center',
maxFontSize: 16,
});
canvas.on('text:changed', function(opt) {
var t1 = opt.target;
if (t1.text.match(/[\r\n]/)) return;
t1.set({
fontSize: t1.maxFontSize,
});
while (t1._textLines.length > 1) {
t1.set({
fontSize: t1.fontSize - 1,
});
}
});
canvas.add(t1);
canvas {
border: 1px solid #999;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>

Calculating offset for HTML5 video

I am tracing a point in an HTML5 video using canvas overlay. The canvas is on top of the video tag with the following style:
#my-canvas { width: 100%; height: 100%; position:absolute !important; z-index:100000; margin: 0 auto; background-color:rgba(68, 170, 213, 0.0); }
The points were captured via separate (Android) app. Here's how I plot the points on the canvas:
MyClass.prototype.drawLine = function(_context, _ctr, _color) {
_context.lineWidth = 2;
_context.lineJoin = 'round';
_context.strokeStyle = _color;
_context.moveTo(this.data["xs"][_ctr]*this.xOffset, this.data["ys"][_ctr]*this.yOffset);
_context.lineTo(this.data["xs"][_ctr+1]*this.xOffset, this.data["ys"][_ctr+1]*this.yOffset);
_context.stroke();
_context.closePath();
}
I multiply the data points with an offset value to compensate for the screen size. This is how I calculate the offset:
MyClass.prototype.calculateOffsets = function() {
this.yOffset = this.video.offsetHeight/parseFloat(this.data["height"]);
this.xOffset = this.video.offsetWidth/parseFloat(this.data["width"]);
}
This code works fine in a landscape video but not in portrait. I might be missing something with the offset calculation. I would appreciate if you can point me to the proper direction.
Thanks in advance.
When you set canvas size using CSS your canvas will actually always be 300x150 pixels. What you draw to it will be relative to that size.
Try instead to remove the 100% width and height from the CSS rule and set the canvas size for its bitmap every time you get an onresize event etc. CSS sets the element size; this will set the bitmap size (element will follow if no CSS is overriding):
_context.canvas.width = window.innerWidth;
_context.canvas.height = window.innerHeight;
and
#my-canvas {width: 100%; height: 100%;position:absolute...
Notice though that changing the canvas size will also clear it so you will have to redraw everything up to that point if that is needed.

Making a div on the fly that is resizable not working

I have a function that creates a div on the fly using jquery, and the user can define several properties to style the div. The problem is that I want the div to be resizable but the resulting div is the size the user defines but I am not able to resize it.
this is my function:
function createDiv(id, divWidth, divHeight, divContent, divBgColor, opacity){
//FIRST HEX TO RGB FOR BG COLOR & OPACITY
var currentColor = hexToRgb(divBgColor);
//CREATE THE WRAPPER DIV
var wrapper = $('<div/>', {
id: id
}).css({
"backgroundColor": 'rgba('+currentColor+' '+opacity+')',
"min-width": divWidth,
"min-height": divHeight
}).resizable({
containment: 'parent',
minHeight: divHeight,
minWidth: divWidth
}).appendTo('.current-layer');
}
This is the call to the function:
onclick="createDiv('1', '200px', '100px', 'text', '#FF0000', 0.5)"
I hope someone can tell me what I am doing wrong! TIA
The parent(containment) must have a width/height higher than the min-width/min-height of the resizable.
Currently width and height is not set, so it will be 100% and 0
Result: you can resize the resizable:
width: 200px up to the width of the containment(100%)
height: 100px up to height of the containment(also 100px, derived from it's content), so the height is unresizable
Demo: http://jsfiddle.net/doktormolle/VnCHA/
I solved the problem and feel like bit of a muppet.
Because the div was created on the fly I had to make it resizable after it was appended to the DOM.

Categories