Edit FabricJS objects by HTML <input> - fabricjs

var canvas = new fabric.Canvas('c');
canvas.add(new fabric.Rect({
left:10,
top:10,
width:50,
height:50,
fill:'#4169e1'
}));
canvas.add(new fabric.Rect({
left:140,
top:140,
width:50,
height:50,
fill:'#800000'
}));
canvas {
border: black solid 1px;
padding: 5px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.min.js"></script>
<input type='color'></input>
<canvas id="c" width="200" height="200"></canvas>
I want to be able to select an object and the input field updates with the color, AND be able to change the color of the object from the input field. I know I can do one way binding with document.getElementById("example").innerHTML and '<input type="color" value="' + canvas.getActiveObject().fill +'">', but what is the best way for two way binding?

You need to use events object:selected selection:cleared to get the selected object. And set the color picker value from selected object fill value.
DEMO
var canvas = new fabric.Canvas('c');
canvas.add(new fabric.Rect({
left: 10,
top: 10,
width: 50,
height: 50,
fill: '#4169e1'
}));
canvas.add(new fabric.Rect({
left: 140,
top: 140,
width: 50,
height: 50,
fill: '#800000'
}));
var colorPick = document.getElementById('colorPick');
var activeSelected;
colorPick.onchange = function() {
if (activeSelected) {
activeSelected.fill = this.value;
activeSelected.dirty = true;
canvas.renderAll();
}
};
canvas.on('object:selected', function(option) {
activeSelected = option.target;
colorPick.value = activeSelected.fill;
})
canvas.on('selection:cleared', function(option) {
activeSelected = null;
console.log(activeSelected)
});
canvas {
border: black solid 1px;
padding: 5px;
margin-top: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.min.js"></script>
<input type='color' id='colorPick'></input>
<canvas id="c" width="200" height="200"></canvas>

Related

Disable Object Selection Outside ClipPath

How can I disable object selection outside of clipPath?
var canvas = new fabric.Canvas('c');
var clipath = new fabric.Rect({ width: 400, height: 300,left:50,fill: '#eee', absolutePositioned: true, selectable: false,hoverCursor: "default",strokeWidth: 0 });
var rect = new fabric.Rect({ width: 100, height: 100, fill: 'red',left:80,top:20 });
rect.clipPath = clipath;
canvas.add(clipath);
canvas.add(rect);
<canvas id="c" width="600" height="350" style="border:1px solid #ccc"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>

Fabric.js: Initial position object outside canvas no longer working

Recently I have started to use a newer version of Fabric.js (from 1.7.22 to 2.3.5). I had to make a few modifications to existing code that seem logical to me. However, I notice that you cannot initially place an object outside the canvas anymore, to reposition it later onto the canvas. Like in the code below. It won't show. My question is: has this changed for some reason, or is this an issue (bug)? And do I have other options than postpone adding the object to the canvas, or using the visible attribute?
$( document ).ready(() => {
const canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 301,
top: 10,
originX: 'left',
originY: 'top',
width: 50,
height: 50,
fill: '#336699'
});
canvas.add(rect);
rect.set({"left": 10});
rect.set({"top": 10});
canvas.renderAll();
});
canvas {
border: 1px solid tomato;
}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="100"></canvas>
You need to use setCoords() after repositioning.
$( document ).ready(() => {
const canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 301,
top: 10,
originX: 'left',
originY: 'top',
width: 50,
height: 50,
fill: '#336699'
});
canvas.add(rect);
rect.set({"left": 10});
rect.set({"top": 10});
rect.setCoords();
canvas.renderAll();
});
canvas {
border: 1px solid tomato;
}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.5/fabric.min.js"></script>
<canvas id="canvas" width="300" height="100"></canvas>

fabric.js how to control selcted element to be not on top [duplicate]

I've a problem with my FabricJS app. By default, the object layer in fabricjs jumps to the top when I select it.
I want to disable this option so that the index of the active element not changing. It's possible ?
You just need to set the preserveObjectStacking options as shown in the below code when setting up the canvas.
var fabricCanvas = new fabric.Canvas("t", { preserveObjectStacking: true });
fabricCanvas
.add(new fabric.Rect({
top: 0,
left: 0,
width: 100,
height: 100,
fill: "green"
}))
.add(new fabric.Rect({
top: 50,
left: 50,
width: 100,
height: 100,
fill: "red"
}))
.add(new fabric.Rect({
top: 100,
left: 100,
width: 100,
height: 100,
fill: "blue"
}))
.renderAll();
canvas {
border: 1px solid black;
}
<canvas id="t" width="400" height="300"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script>

How to create a kite shaped surface [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am trying to build a surface with Famo.us that is shaped like a kite.
A kite is a quadrilateral whose four sides can be grouped into two pairs of equal-length sides that are adjacent to each other. I am looking to transform the rectangle of the shape of a surface into a kite shape. I can create parallelogram by skewX or skewY. A parallelogram also has two pairs of equal-length sides, but they are opposite each other rather than adjacent(like in a kite).
The surface is a div, and I want to change the shape from a surface from a square/rectangle into a kite. I trying to make a hex grid. I am surprised that a highly mathematical JavaScript Famo.us web platform does not have a Triangular surface. I like a Famo.us only solution, it possible.
Your question is valid, but there is a caveat. A surface (div) of this shape requires us to create a two part style using after. Your use case may limit the use of this solution.
Without Famo.us: Using a div and css you can create a kite shape.
<div class="kite-css"></div>
.kite-css {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
position: relative;
}
.kite-css:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
Using Famo.us: Use some modified css from above and adding the class to the Famo.us surface. I added some background-color of the Surface to highlight the surface area that will be used for rendering size. I added some text in the content of the surface to show how text is affected by this method.
Issues:
The true center of the surface is the center of the shaded area in the image above. This is the element created by Famo.us and the lower piece is created by the style using after.
The usable content starts at the center of the top piece, because the border squeezes out all sides of the square.
.kite-shape {
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
}
.kite-shape:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
var kite = new Surface({
size: [100, 100],
classes: ['kite-shape','double-sided'],
content: 'Famo.us Kite',
properties: {
backgroundColor: 'rgba(0,0,0,0.05)',
fontSize: '0.9em'
}
});
Considerations:
You could put the kite shape inside your surface with your text content prior (example snippet #2)
You could also use the ImageSurface and make a kite image to be used by the surface.
Example code snippet below with a rotation effect, so you can play with it.
define('main', function (require, exports, module) {
var Engine = require('famous/core/Engine');
var OptionsManager = require('famous/core/OptionsManager');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var RenderNode = require('famous/core/RenderNode');
var Transform = require('famous/core/Transform');
var TransitionableTransform = require('famous/transitions/TransitionableTransform');
var mainContext = Engine.createContext();
mainContext.setPerspective(1000);
var kite = new Surface({
classes: ['kite-shape','double-sided'],
content: 'Famo.us Kite',
properties: {
backgroundColor: 'rgba(0,0,0,0.05)',
fontSize: '0.9em'
}
});
var tt = new TransitionableTransform();
mainContext.add(new Modifier({
size: [100, 100],
origin:[0.5, 0.5],
align:[0.5, 0.5],
transform: rotate
})).add(kite);
var initialTime = Date.now();
function rotate() {
var radians = 0.001 * (Date.now() - initialTime);
tt.set(Transform.rotateAxis([0,1,0.25], Math.PI * radians));
return tt.get();
}
});
require(['main']);
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>
<div class="kite-css">CSS</div>
<style>
.double-sided {
-webkit-backface-visibility: visible;
backface-visibility: visible;
}
.kite-css {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
position: relative;
}
.kite-css:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
.kite-shape {
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
}
.kite-shape:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
</style>
Example code snippet #2.
Has the kite shape inside a surface.
define('main', function (require, exports, module) {
var Engine = require('famous/core/Engine');
var OptionsManager = require('famous/core/OptionsManager');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var RenderNode = require('famous/core/RenderNode');
var Transform = require('famous/core/Transform');
var TransitionableTransform = require('famous/transitions/TransitionableTransform');
var mainContext = Engine.createContext();
mainContext.setPerspective(1000);
var kite = new Surface({
size: [100, 300],
classes: ['double-sided'],
content: 'Famous Kite<div class="kite-css"></div>',
properties: {
backgroundColor: 'rgba(0,0,0,0.05)',
fontSize: '0.9em',
lineHeight: '12px'
}
});
var tt = new TransitionableTransform();
mainContext.add(new Modifier({
size: [100, 100],
origin:[0.5, 0.5],
align:[0.5, 0.5],
transform: rotate
})).add(kite);
var initialTime = Date.now();
function rotate() {
var radians = 0.001 * (Date.now() - initialTime);
tt.set(Transform.rotateAxis([0,1,0.25], Math.PI * radians));
return tt.get();
}
});
require(['main']);
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>
<div class="kite-css">CSS</div>
<style>
.double-sided {
-webkit-backface-visibility: visible;
backface-visibility: visible;
}
.kite-css {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
position: relative;
}
.kite-css:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
.kite-shape {
border: 50px solid transparent;
border-bottom: 50px solid red;
top: -40px;
}
.kite-shape:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 90px solid red;
z-index: -1
}
</style>

YUI Tutorial not working

Why does this code from this YUI3 example not work for me?
HTML:
<!-- The original body content is above -->
<div id="form_container">
<form class="yui3-widget-bd" id="theme_form" action="#" method="get">
<fieldset>
<h3>Update Theme</h3>
<label for="font_size">Font size:</label>
<input type="text" size="3" id="font_size" value="16px">
<label for="heading_color">Heading color:</label>
<input type="text" size="12" id="heading_color" value="#005A9C">
<label for="link_hover">Link hover backgound:</label>
<input type="text" size="12" id="link_hover" value="#ffa">
</fieldset>
<input type="submit">
</form>
</div>
Javascript:
// Create a new YUI instance, requiring stylesheet, overlay, slider, and the
// dd-plugin to make the overlay draggable
YUI({
filter: 'raw'
}).use("stylesheet", "overlay", "slider", "dd-plugin", function(Y) {
var myStyleSheet = new Y.StyleSheet(),
overlayContent = Y.one('#form_container'),
overlay, slider, slider_container, fontSizeInput;
// Create the Overlay, using the form container as the contentBox.
// The form is assigned a class yui-widget-bd that will be automatically
// discovered by Overlay to populate the Overlay's body section.
// The overlay is positioned in the top right corner, but made draggable
// using Y.Plugin.Drag, provided by the dd-plugin module.
overlay = new Y.Overlay({
srcNode: overlayContent,
width: '225px',
align: {
points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TR]
},
plugins: [Y.Plugin.Drag]
}).render();
// Slider needs a parent element to have the sam skin class for UI skinning
overlayContent.addClass('yui3-skin-sam');
// Progressively enhance the font-size input with a Slider
fontSizeInput = Y.one('#font_size');
fontSizeInput.set('type', 'hidden');
fontSizeInput.get('parentNode').insertBefore(
Y.Node.create('6 <span></span> 36'), fontSizeInput);
slider_container = fontSizeInput.previous("span");
// Create a Slider to contain font size between 6px and 36px, using the
// page's current font size as the initial value.
// Set up an event subscriber during construction to update the replaced
// input field's value and apply the change to the StyleSheet
slider = new Y.Slider({
length: '100px',
min: 6,
max: 36,
value: parseInt(Y.one('body').getStyle('fontSize')) || 13,
after: {
valueChange: function(e) {
var size = e.newVal + 'px';
this.thumb.set('title', size);
fontSizeInput.set('value', size);
myStyleSheet.set('body', {
fontSize: size
});
}
}
}).render(slider_container);
// The color inputs are assigned keyup listeners that will update the
// StyleSheet if the current input value is a valid CSS color value
// The heading input affects all h1s, h2, and h3s
Y.on('keyup', function(e) {
var color = this.get('value');
console.log(color);
if (isValidColor(color)) {
console.log("Valid color", myStyleSheet);
myStyleSheet.set('h1, h2, h3', {
color: color
});
}
}, '#heading_color');
// The link hover affects the background color of links when they are
// hovered. There is no way other than via stylesheet modification to
// change pseudo-class styles.
Y.on('keyup', function(e) {
var color = this.get('value');
if (isValidColor(color)) {
myStyleSheet.set('a:hover', {
backgroundColor: color
});
}
}, '#link_hover');
// Progressive form enhancement complete, now prevent the form from
// submitting normally.
Y.on('submit', function(e) {
e.halt();
}, '#theme_form');
// A rudimentary validator to make sure we're not trying to set
// invalid color values in StyleSheet.
function isValidColor(v) {
return /^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(v) || /^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$/.test(v) || /^[a-z]{3,}$/i.test(v);
}
});
CSS:
/* For supporting browsers, the overlay is rendered semi-transparent with
* fancy rounded corners */
.yui3-overlay {
background: rgba(128,128,128,0.3);
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
padding: 7px;
cursor: move;
}
.yui3-overlay-content {
background: rgba(205,205,205,0.3);
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
padding: 1px;
}
.yui3-overlay form {
background: #f2fbff;
border: 2px solid #fff;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
margin: 0;
padding: 0;
font-size: 13px;
}
.yui3-overlay fieldset {
border: 1px solid #bcd;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
margin: 0;
padding: 20px;
}
.yui3-overlay h3 {
border-bottom: 2px solid #fff;
color: #479;
background: transparent;
margin: 0;
font-size: 175%;
}
.yui3-overlay label {
display: block;
margin: 1.3em 0 0.5ex;
font-weight: bold;
color: #003;
}
.yui3-overlay p {
margin: 2em 0 0;
}
/* override the move cursor for the Slider */
.yui3-overlay .yui3-slider:hover {
cursor: default;
}
I just copied and pasted the code, can anyone help?
Your tag is missing class="yui3-skin-sam yui-skin-sam"
It appears to be working. I copied/pasted your code into this jsfiddle. Change with the slider and header color change field, it seems to update the color and size.
This is not the best forum to do support debugging.
You're welcome to ask in the #yui channel on freenode rather than go through slow, back and forth debugging here.

Resources