How to make rooftext effect and valley text effect in HTML5 (or Fabric.js)
Here is a modified version of the original code (the provided code in question has changed values compared to my original code.. .-) ) which can produce all these shapes just by playing around with the parameters:
The roof is not super but I'll leave it to you to add scaling support as this is meant as an example.
ONLINE DEMO HERE
Initialization:
var ctx = demo.getContext('2d'), /// context
font = '64px impact', /// font
w = demo.width, /// cache canvas width and height
h = demo.height,
curve, /// radius
offsetY, /// offset for text
bottom, /// bottom of text
textHeight, /// text height (region of text)
isTri = false, /// is triangle shaped (roof)
dltY, /// delta for triangle
angleSteps = 180 / w, /// angle steps for curved text
i = w, /// "x" backwards
y, /// top of text
/// offscreen canvas that holds original text
os = document.createElement('canvas'),
octx = os.getContext('2d');
os.width = w;
os.height = h;
/// set font on off-screen canvas where we draw it
octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';
Main function:
/// render
function renderBridgeText() {
/// demo stuff snipped (see link)
/// clear canvases
octx.clearRect(0, 0, w, h);
ctx.clearRect(0, 0, w, h);
/// draw text (text may change)
octx.fillText(iText.value.toUpperCase(), w * 0.5, 0);
/// slide and dice
dltY = curve / textHeight; /// calculate delta for roof/triangle
y = 0; /// reset y in case we do roof
i = w; /// init "x"
while (i--) {
if (isTri) {
/// bounce delta value mid-way for triangle
y += dltY;
if (i === (w * 0.5)|0) dltY = -dltY;
} else {
/// calc length based on radius+angle for curve
y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
}
/// draw a slice
ctx.drawImage(os, i, 0, 1, textHeight,
i, h * 0.5 - offsetY / textHeight * y, 1, y);
}
}
Bridge text effect using Fabric.js
There is a nice solution in this question using basic canvas api:
How to make rooftext effect and valley text effect in HTML5 (or Fabric.js)
I find it's diffcult to use Fabric.js to recreate it since it seems Fabric.image did not implement context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
but only context.drawImage(img,x,y,width,height);
I could be wrong as I just take a first quick look of this library 15 minutes ago, have look at the solution any way, hope it helps.
Text smear effect in JavaScript
Many possibilities.
Here is an example of a simple WEBGL 2D texture drawn onto a standard 2D canvas. There is a bit of boilerplate for mouse,canvas,webGL so you will have to pick it apart yourself.
The FX is in the Fragment Shader. Rather than move the texture coords I just mapped a 2D vector field over the image (pretty much randomly made it up as i went) The vectors offset the pixel lookup from the texture. The amount
controlled by mouse up and down controls the amount of the FX and the mouse from left to right moves the Phase
setting.
Moving mouse to the top of the image reduces the effect amount. Bottom right is at max.
.
The function at the bottom webGLRender
sets the fragment shader values and renders the webGl then 2D context drawImage
to render to display canvas. The Fragment shader is above that.
As the webGL image is rendered via ctx.draw2D it is easy to resize making the webGL render total display resolution independent. If you have performance issues (image in the mega pixel * 4 + range) you can reduce the input image size
WebGL can not render images that are not from the same domain (tained) unlike 2D canvas webGL requires access to the pixel data to draw textures and thus tained images will make it throw security errors. I have used a 2d canvas rather than an image as I could not find an image the would not taint the canvas.
// boiler plateconst U = undefined;const RESIZE_DEBOUNCE_TIME = 100;var w,h,cw,ch,canvas,ctx,mouse,createCanvas,resizeCanvas,setGlobals,globalTime=0,resizeCount = 0; var L = typeof log === "function" ? log : function(d){ console.log(d); }createCanvas = function () { var c,cs; cs = (c = document.createElement("canvas")).style; cs.position = "absolute"; cs.top = cs.left = "0px"; cs.zIndex = 1000; document.body.appendChild(c); return c;}resizeCanvas = function () { if (canvas === U) { canvas = createCanvas(); } canvas.width = window.innerWidth; canvas.height = window.innerHeight; ctx = canvas.getContext("2d"); if (typeof setGlobals === "function") { setGlobals(); } if (typeof onResize === "function"){ resizeCount += 1; setTimeout(debounceResize,RESIZE_DEBOUNCE_TIME);}}function debounceResize(){ resizeCount -= 1; if(resizeCount <= 0){ onResize();}}setGlobals = function(){ cw = (w = canvas.width) / 2; ch = (h = canvas.height) / 2; mouse.updateBounds(); }mouse = (function(){ function preventDefault(e) { e.preventDefault(); } var mouse = { x : 0, y : 0, w : 0, alt : false, shift : false, ctrl : false, buttonRaw : 0, over : false, bm : [1, 2, 4, 6, 5, 3], active : false,bounds : null, crashRecover : null, mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",") }; var m = mouse; function mouseMove(e) { var t = e.type; m.x = e.clientX - m.bounds.left; m.y = e.clientY - m.bounds.top; m.alt = e.altKey; m.shift = e.shiftKey; m.ctrl = e.ctrlKey; if (t === "mousedown") { m.buttonRaw |= m.bm[e.which-1]; } else if (t === "mouseup") { m.buttonRaw &= m.bm[e.which + 2]; } else if (t === "mouseout") { m.buttonRaw = 0; m.over = false; } else if (t === "mouseover") { m.over = true; } else if (t === "mousewheel") { m.w = e.wheelDelta; } else if (t === "DOMMouseScroll") { m.w = -e.detail; } if (m.callbacks) { m.callbacks.forEach(c => c(e)); } if((m.buttonRaw & 2) && m.crashRecover !== null){ if(typeof m.crashRecover === "function"){ setTimeout(m.crashRecover,0);}} e.preventDefault(); } m.updateBounds = function(){ if(m.active){ m.bounds = m.element.getBoundingClientRect(); } } m.addCallback = function (callback) { if (typeof callback === "function") { if (m.callbacks === U) { m.callbacks = [callback]; } else { m.callbacks.push(callback); } } else { throw new TypeError("mouse.addCallback argument must be a function"); } } m.start = function (element, blockContextMenu) { if (m.element !== U) { m.removeMouse(); } m.element = element === U ? document : element; m.blockContextMenu = blockContextMenu === U ? false : blockContextMenu; m.mouseEvents.forEach( n => { m.element.addEventListener(n, mouseMove); } ); if (m.blockContextMenu === true) { m.element.addEventListener("contextmenu", preventDefault, false); } m.active = true; m.updateBounds(); } m.remove = function () { if (m.element !== U) { m.mouseEvents.forEach(n => { m.element.removeEventListener(n, mouseMove); } ); if (m.contextMenuBlocked === true) { m.element.removeEventListener("contextmenu", preventDefault);} m.element = m.callbacks = m.contextMenuBlocked = U; m.active = false; } } return mouse;})();
resizeCanvas(); mouse.start(canvas,true); window.addEventListener("resize",resizeCanvas); function display(){ ctx.setTransform(1,0,0,1,0,0); // reset transform ctx.globalAlpha = 1; // reset alpha ctx.clearRect(0,0,w,h); if(webGL !== undefined){ webGLRender(); }}function update(timer){ // Main update loop globalTime = timer; display(); // call demo code requestAnimationFrame(update);}requestAnimationFrame(update);var globalTime = new Date().valueOf(); // global to this
// creates vertex and fragment shaders function createProgramFromScripts( gl, ids) { var shaders = []; for (var i = 0; i < ids.length; i += 1) { var script = shadersSource[ids[i]]; if (script !== undefined) { var shader = gl.createShader(gl[script.type]); gl.shaderSource(shader, script.source); gl.compileShader(shader); shaders.push(shader); }else{ throw new ReferenceError("*** Error: unknown script ID : " + ids[i]); } } var program = gl.createProgram(); shaders.forEach((shader) => { gl.attachShader(program, shader); }); gl.linkProgram(program); return program; }
// setup simple 2D webGL image processorvar webGL;function startWebGL(image) { // Get A WebGL context webGL = document.createElement("canvas"); webGL.width = image.width; webGL.height = image.height; webGL.gl = webGL.getContext("webgl"); var gl = webGL.gl; var program = createProgramFromScripts(gl, ["VertexShader", "FragmentShader"]); gl.useProgram(program); var positionLocation = gl.getAttribLocation(program, "a_position"); var texCoordLocation = gl.getAttribLocation(program, "a_texCoord"); var texCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0,1.0, 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, 1.0]), gl.STATIC_DRAW); gl.enableVertexAttribArray(texCoordLocation); gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
// lookup uniforms for frag shader var locs = {} locs.timer = gl.getUniformLocation(program, "time"); // the time used to control waves locs.phase = gl.getUniformLocation(program, "phase"); // Sort of phase, moves to attractors around locs.amount = gl.getUniformLocation(program, "amount"); // Mix amount of effect and flat image webGL.locs = locs; gl.uniform2f(resolutionLocation, webGL.width, webGL.height); var buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); setRectangle(gl, 0, 0, image.width, image.height);}function setRectangle(gl, x, y, width, height) { var x1 = x; var x2 = x + width; var y1 = y; var y2 = y + height; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW);}
function randomInt(range) { return Math.floor(Math.random() * range);}
var shadersSource = { VertexShader : { type : "VERTEX_SHADER", source : ` attribute vec2 a_position; attribute vec2 a_texCoord; uniform vec2 u_resolution; varying vec2 v_texCoord; void main() { vec2 zeroToOne = a_position / u_resolution; vec2 zeroToTwo = zeroToOne * 2.0; vec2 clipSpace = zeroToTwo - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); v_texCoord = a_texCoord; }` }, FragmentShader : { type : "FRAGMENT_SHADER", source : ` precision mediump float; uniform sampler2D u_image; uniform float time; uniform float phase; uniform float amount; varying vec2 v_texCoord; vec2 offset; float dist; float edge; float v; vec2 pos1 = vec2(0.5 + sin(phase * 0.03)*1.3, 0.5 + cos(phase * 0.032)*1.3); vec2 pos2 = vec2(0.5 + cos(phase * 0.013)*1.3,0.5 + cos(phase*0.012)*1.3); void main() { dist = distance(pos1,v_texCoord) * distance(pos2,v_texCoord);
edge = 1. - distance(vec2(0.5,0.5),v_texCoord) / 0.707; v = time * dist * 0.0001 * edge * phase; offset = vec2( v_texCoord.x + sin(v+time) * 0.1 * edge * amount, v_texCoord.y + cos(v+time) * 0.1 * edge * amount ); //offset = smoothstep(v_texCoord.x,offset.x,abs(0.5-v_textCoord.x) ); gl_FragColor = texture2D(u_image, offset); }` }}
var md = 0;var mr = 0;var mdy = 0;var mry = 0;function webGLRender(){ var gl = webGL.gl; md += (mouse.x / canvas.width - mr) * 0.16; md *= 0.18; mr += md; mdy += (mouse.y - mry) * 0.16; mdy *= 0.18; mry += mdy; gl.uniform1f(webGL.locs.timer, globalTime/100); gl.uniform1f(webGL.locs.phase, mr * 400); gl.uniform1f(webGL.locs.amount, ((mry/canvas.height)) * 9); gl.drawArrays(gl.TRIANGLES, 0, 6); ctx.drawImage(webGL,0,0, canvas.width, canvas.height);}
var image = document.createElement("canvas");image.width = 1024;image.height = 512;image.ctx = image.getContext("2d");image.ctx.font = "192px Arial";image.ctx.textAlign = "center";image.ctx.textBaseline = "middle";image.ctx.lineJoin = "round";image.ctx.lineWidth = 32;image.ctx.strokeStyle = "red";image.ctx.fillStyle = "black";image.ctx.strokeText("WOBBLE",512,256);image.ctx.lineWidth = 16;image.ctx.strokeStyle = "white";
image.ctx.strokeText("WOBBLE",512,256);image.ctx.fillText("WOBBLE",512,256);image.ctx.font = "32px Arial";image.ctx.fillText("Mouse position on image controls wobble",512,32);image.ctx.fillText("Using WebGL and 2D Canvas",512,512-32);
startWebGL(image);/*var image = new Image(); // load imageimage.src = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1"; // MUST BE SAME DOMAIN!!!image.onload = function() { startWebGL(image);}*/
overlaping canvas a div using javascript
You can place both in a container and use absolute positioning, as so:
<div id="container">
<canvas id=demo width=400 height=300></canvas>
<div href="#" class="item" data-bind="draggable:true,droppable:true">
<span data-bind="click:$parent.remove">[x]</span><br/><br/>
<center><span class="text" data-bind="text:$data"></span><input class="edit_text"/></center>
</div>
</div>
and then in the style sheet:
#container {
position: relative;
}
#demo, div[href="#"] {
position: absolute;
top: 0px;
left: 0px;
}
Related Topics
Css: How to Set Image Size Relative to Parent Height
Space Between Divs - Display Table-Cell
Use HTML5 (Datalist) Autocomplete with 'Contains' Approach, Not Just 'Starts With'
Get Content Between a Pair of HTML Tags Using Bash
How to Make a Div 50Px Less Than 100% in CSS3
How to Export HTML Table Data as .CSV File
CSS Transition - Eases in But Doesn't Ease Out
How to Embed a Swf File in an HTML Page
Making a Div That Covers the Entire Page
iOS 11 Safari Bootstrap Modal Text Area Outside of Cursor
HTML Radio Buttons Allowing Multiple Selections
Pixelated Edge Around a CSS Circle with Overflow: Hidden;
Creating a 'New' Spiky Label with 24 or Above Point Burst
How to Remove/Ignore :Hover CSS Style on Touch Devices
Z-Index Not Working with Position Absolute