I want to create a div overlay, set at 5% opacity, which creates a diagonal bounding box around each of the lines of text in this image. I have the coordinates of each of the four points I need to draw the bounding box, which are encoded as attributes in an XML element which contains the text of individual line as its data. It seems to me that since I have the x,y coordinates for the four corners, I should be able to create the overlay -- but I cannot figure out what the proper syntax would be to mark out the div. Someone suggested to me using the transform functions for CSS (which was the right call as I originally framed this question) but that sounds like I'd be basically writing eight separate pieces of css, one for each line -- which could get messy since there are potentially 118 pictures like this that I would be writing custom pieces of CSS for.
Am I wrong in thinking this can be done programmatically, and if not can someone point me at some methods for doing so?
Yes, it is possible this way, with simple html markup:
<div class="image_box" data-cords="20,50,210,50,50,250,240,250">I am the text inside the div, I can be in several lines. It is important for text stay vertical and it is important the text to follow boundary box.</div>
Than do some script magic:
$.fn.skewText = function () {
return this.each(function (i) {
var thisText = $(this);
var coords = thisText.data('cords').split(',');
/* Calculate degree */
var deg = Math.tan((coords[5] - coords[1]) / (coords[4] - coords[0])) * 57.2957795;
/* Skew pixels for calculations */
var skewVal = coords[4] - coords[0];
/* Calculate position */
var cssWidth = (coords[2] - coords[0] - skewVal) + 'px';
var cssHeight = (coords[5] - coords[1]) + 'px';
var cssTop = coords[1] + 'px';
var cssLeft = (coords[0] * 1 + skewVal) + 'px'; /* Add a half of skew */
/* Wrapp and apply styles */
thisText.wrapInner('<div class="skew_padding" />').wrapInner('<div class="skew_text" />');
var skewText = thisText.find('.skew_text');
skewText.css({
'transform': 'skew(' + deg + 'deg)',
'top': cssTop,
'left': cssLeft,
'width': cssWidth,
'height': cssHeight,
'background': 'none rgba(0,0,0,.5)'
});
/* Now skew back each letter inside */
var skewPadding = skewText.find('.skew_padding');
var letters = skewPadding.text().split(' ');
var newText = '<span>' + letters.join('</span> <span>') + '</span>';
skewPadding.html(newText);
skewPadding.find('span').css({
'display': 'inline-block',
'transform': 'skew(' + (-deg) + 'deg)'
});
});
};
$('[data-cords]').skewText();
That is possible with this css:
.image_box {
position: relative;
width: 300px;
height: 300px;
background: yellow;
}
.skew_text {
position: absolute;
}
.skew_padding {
padding: 10px;
}
Related
I have found this pen on codepen. I would like to use this effect, but in a grayscale.
Could anyone help me?
Thanks in advance!
// Create a HTML div Element called 'page'
var page = document.createElement('DIV');
// Gives the page variable full height
page.style.height = '100vh';
// Applies the page element to the document(web page)
document.body.appendChild(page);
//Creates variables for x & y for know where our mouse is
//x is for horizontal values, and y for vertical ones
var x = 0;
var y = 0;
// Add Event Listener for page. Listens for any mouse movement
// inside the page element. If found, run function below
page.addEventListener('mousemove', function(event) {
//Takes the mouse movement we listened for and saves it into two variables
x = event.clientX;
y = event.clientY;
//Here we set the background color to the x & y value that the mouse has over the web page. See css part for rgb explaination
page.style.backgroundColor = 'rgb(' + x + ', ' + y + ', 100)';
//By writing variable + ', ' we combine the value with text to make it write like rgb(x, y, 100); when sent to style part (css)
//Adds a text element to the page. It writes out the x & y value
page.textContent = x + ', ' + y;
});
// Find the css element called 'box' to use in future
var box = document.getElementById('box');
//Function for a box that follows the mouse around
var mousebox = function() {
//Calls the css code to push the box away from the left & top
//the same x & y values that the mouse has
box.style.left = x + 'px';
box.style.top = y + 'px';
}
// Find the css element called 'rbox' to use in future
var rbox = document.getElementById('rbox');
//Variable to hold our current angle/degree of rbox
var degree = 0;
//Setup a rotating box in the center
var rotatebox = function(){
//Adds rotation, but makes it go (357, 358, 359, 0, 1, 2)
degree = (degree + 1) % 360;
//adds the current rotation to the rbox
rbox.style.transform = 'rotate('+degree+'deg)';
//Pushes the box from left & top by half of window width & height
rbox.style.left = window.innerWidth / 2 + 'px';
rbox.style.top = window.innerHeight / 2 + 'px';
}
//Sets up an update interval of how often both boxes happen. Number is in milliseconds so 100ms = 10 times per second
setInterval(mousebox,100);
setInterval(rotatebox,10);
body {
margin: 0; /* Removes any margin so anything within the body fills the space */
}
/* Box that will follow the mouse around */
#box {
position: absolute; /* Allows us to move it around */
color: #FFF; /* Makes the text white */
font-size: 24px; /* Makes the box text larger (24 pixels tall) */
transition: ease-out 1s; /* Gives a smooth movement following the box, s for seconds. Feel free to increase lower */
}
/* Rotating box that will spin in the middle */
#rbox {
position: absolute; /* Allows us to move it around */
width: 50px; /* Size with width/height */
height: 50px;
background-color: #FFF; /* Makes the background white, if removed its transparent. If all are the same you can write just 3, but otherwise hexagon letter/numbers come in 6 */
/* When talking RGB colour, 0 or 00 gives no colour (black) while 255 or FF is full colour */
/* RGB: For red #FF0000 , green is #00FF00 , and blue is #0000FF. Inbetween these you can mix and match*/
/* Use to find specific colours you like https://www.w3schools.com/colors/colors_picker.asp */
color: #000; /* Text in the box is black */
text-align: center; /* Puts the text in middle */
font-size: 36px; /* Text size, fits the size we set above */
}
<div id="box">Hello!</div>
<div id="rbox">:)</div>
Just use a single variable in all three color's places, i.e rgb(x, x, x)
var page = document.createElement('DIV');
page.style.height = '100vh';
document.body.appendChild(page);
var x = 0;
var y = 0;
page.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
// ================== Solution ======================
Gray = y; // or Math.min(x, y) or (x + y) / 2
color = [Gray, Gray, Gray].join(", ");
page.style.backgroundColor = 'rgb(' + color + ')';
// =====================================================
page.textContent = x + ', ' + y;
});
var box = document.getElementById('box');
var mousebox = function() {
box.style.left = x + 'px';
box.style.top = y + 'px';
}
var rbox = document.getElementById('rbox');
var degree = 0;
var rotatebox = function() {
degree = (degree + 1) % 360;
rbox.style.transform = 'rotate(' + degree + 'deg)';
rbox.style.left = window.innerWidth / 2 + 'px';
rbox.style.top = window.innerHeight / 2 + 'px';
}
setInterval(mousebox, 100);
setInterval(rotatebox, 10);
body {
margin: 0;
/* Removes any margin so anything within the body fills the space */
}
/* Box that will follow the mouse around */
#box {
position: absolute;
/* Allows us to move it around */
color: #FFF;
/* Makes the text white */
font-size: 24px;
/* Makes the box text larger (24 pixels tall) */
transition: ease-out 1s;
/* Gives a smooth movement following the box, s for seconds. Feel free to increase lower */
}
/* Rotating box that will spin in the middle */
#rbox {
position: absolute;
/* Allows us to move it around */
width: 50px;
/* Size with width/height */
height: 50px;
background-color: #FFF;
/* Makes the background white, if removed its transparent. If all are the same you can write just 3, but otherwise hexagon letter/numbers come in 6 */
/* When talking RGB colour, 0 or 00 gives no colour (black) while 255 or FF is full colour */
/* RGB: For red #FF0000 , green is #00FF00 , and blue is #0000FF. Inbetween these you can mix and match*/
/* Use to find specific colours you like https://www.w3schools.com/colors/colors_picker.asp */
color: #000;
/* Text in the box is black */
text-align: center;
/* Puts the text in middle */
font-size: 36px;
/* Text size, fits the size we set above */
}
<div id="box">Hello!</div>
<div id="rbox">:)</div>
Explanation
There are several ways of converting RGB to Gray Scale, but none of them apply in this case. Take a look at all of them here: Gray Scale Algorithms
Using a single variable say rgb(y, y, y) works because, gray scale colors generally appear like this: #d3d3d3, rgb(63,63,63), etc. A single value in all channels
If you want to use both the variables, you can do Math.min(x, y) or (x + y) / 2 and then pass it to a variable Gray, which then can be set like so: rgb(Gray, Gray, Gray)
color = [Gray, Gray, Gray].join(", "), this just joins the values separated by comma, in order to avoid writing comma manually.
Change this line:
//Here we set the background color to the x & y value that the mouse has over the web page. See css part for rgb explaination
page.style.backgroundColor = 'rgb(' + x + ', ' + y + ', 100)';
To this
page.style.backgroundColor = 'grayscale(rgb(' + x + ', ' + y + ', 100))';
So I've been trying to integrate flot into some of our standard reporting stuff. I looked at some of the flot examples and cobbled together some code that generates a flot plot based on some data that we generate a report on.
From one of the flot examples, I found that you could make a tooltip appear over the graph through some javascript. It works great. My one issue, that I cannot seem to resolve, is with the tooltip. Occasionally, when the tooltip gets to be on the far right of the graph, such that it would render off the side of the page, it renders off the side of the page.
This is problematic because in order to clearly read the tooltip at that point you must scroll the page to the right, while keeping the mouse on the relevant data piece. To solve this I am trying to render the tooltip to the left of the cursor when the cursor would be past the left half of the plot area. However, I have so far only been successful at determining when the cursor is past the left half of the screen, and my attempts to reposition the div have been fruitless.
Relevant Code:
function showTooltip(x, y, msg) {
flot_tooltip = $("<div id = 'flot_tooltip'>" + msg + '</div>').css({
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #000',
background: '#eee',
padding: '2px',
opacity: '0.75'
}).appendTo('body').fadeIn(150)
adjustForX(flot_tooltip)
}
function adjustForX(flot_tooltip){
if ($(flot_tooltip).offset().left > window.innerWidth/2) {
//alert($(flot_tooltip).width())
//next need to adjust the left position of the element
}
}
Full Fiddle
Sorry for the long-winded explanation,
any guidance would be much appreciated.
I had the same problem on one of my pages and solved it with this code:
function showTooltip(x, y, contents) {
var params = {
position: 'absolute',
display: 'none',
border: '2px solid #333333',
'border-radius': '3px',
padding: '3px',
size: '10',
'background-color': 'lightyellow',
opacity: 0.90
};
if (x < 0.8 * $(window).width()) {
params.left = x + 20;
}
else {
params.right = $(window).width() - x + 20;
}
if (y < 0.8 * $(window).height()) {
params.top = y + 5;
}
else {
params.bottom = $(window).height() - y + 10;
}
$('<div id="tooltip">' + contents + '</div>').css(params).appendTo('body').fadeIn(200);
}
Here I compare the xand yposition values to the window size and position the tooltip to the left of the mouse position if the mouse position is near the right border and above the mouse position if it is near the bottom.
I would like to get a button-like object consisting of a SVG rectangle as the background and HTML text in the foreground. The Raphael SVG library offers nice possibilities to create, modify and animate SVG elements.
I found a solution to draw HTML text in a DIV element along/over the Raphael objects. How can I use the animating methods from Raphael to make the text move with the background?
I am only interested in basic 2D movement, no rotation or deformation ...
I know I could use SVG text element which is supported by Raphael, but this does not allow me text-wrapping, text-styling (css). I was tried unsuccessfully to find a method to get the coordinates of the animated object during animation.
Here is some sample code in coffeescript inspired by the above example mad eby Kelley Reynolds. My problem is how to synchronize thy movement of the background with the overlaying div :
nodeBox = (paper, params, attrs) ->
params = params or {}
attrs = attrs or {}
#paper = paper
#x = params.x or 0
#y = params.y or 0
#width = params.width or #paper.width
#height = params.height or #paper.height
#xMargin = params.xMargin or 5
#yMargin = params.yMargin or 5
#rounding = params.rounding or 0
#backgBox = this.paper.rect(#x-#xMargin, #y-#yMargin, #width+2*#xMargin, #height+2*#yMargin, this.rounding).attr(attrs)
containerId = #backgBox.node.parentNode.parentNode.id
containerId = containerId or #backgBox.node.parentNode.parentNode.parentNode.id
#container = jQuery('#' + containerId)
#div = jQuery('<div style="position: absolute; overflow: auto; width: 0; height: 0;"></div>').insertAfter(#container)
jQuery(document).bind('ready', this, (event) ->
event.data.update()
)
jQuery(window).bind('resize', this, (event) ->
event.data.update()
)
return this
# update function
nodeBox::update = () ->
offset = #container.offset()
#div.css(
'top': (#y + (#rounding) + (offset.top)) + 'px',
'left': (#x + (#rounding) + (offset.left)) + 'px',
'height': (#height - (#rounding*2) + 'px'),
'width': (#width - (#rounding*2) + 'px')
)
# animate function
nodeBox::animate = (attrs, duration, type) ->
#backgBox.animate(attrs, duration, type)
###
Animation of the div ???
###
$(document).ready ->
paper = new Raphael document.getElementById('canvas_container'), '100%', '100%'
node1 = new nodeBox(paper, x:200, y:200, width:200, height:60, rounding: 10, xMargin: 8, yMargin: 4, 'showBorder': true).attr(fill: 'lightblue', stroke: '#3b4449', 'stroke-width': 3)
node1.div.html('This is some crazy content that goes inside of that box that will wrap around.')
node1.div.css('font-family': 'Helvetica','font-size': 16, 'text-align': 'justify')
# animate :
node1.animate({x: moveX}, 1000, 'bounce')
So I figured this out by myself. First possibility is to use the eve library, which already comes with Raphael 2.x. You can update the coordinates of the div on every frame of the animation corresponding to the coordinates of the background-box using eve.on() :
nodeBox::animate = (attrs, duration, type) ->
offset = #canvasContainer.offset()
strokeWidth = #backgBox.attrs['stroke-width']
textBox = #div
rounding = #rounding
xMargin = #xMargin
yMargin = #yMargin
### we animate the underlying box
#backgBox.animate(attrs, duration, type, eve.unbind('raphael.anim.frame.' + #backgBox.id, onAnimate))
### the coordinates of the div are updated on every frame
eve.on('raphael.anim.frame.' + #backgBox.id, onAnimate = (animationObject) ->
textBox.css(
'top': (#attrs.y + (rounding) + (yMargin) + (offset.top) + strokeWidth) + 'px',
'left': (#attrs.x + (rounding) + (xMargin) + (offset.left) + strokeWidth) + 'px', # scrollbar width
'height': (#attrs.height - (rounding*2) - (yMargin*2) - strokeWidth + 'px'),
'width': (#attrs.width - (rounding*2) - (xMargin*2) - strokeWidth + 'px')
)
)
The downside of this solution is, that it does not feel very smooth, one can already see the text "following" the box. Therefore I am no trying the GreenSock Animation Platform which comes with an plugin for Raphael and should offer synchronous animation of the vector graphics and the overlying DOM. Take a look here
I have an input string like this:
{ (3200, 1080), (1280, 0) ; (1280, 1024), (0, 0) }
which is basically an input I get from my c# program which takes the coordinates of my screens.
The numbers in brackets are coordinates of the lower right and upper left point and define a rectangle. For example:
(1280, 1024), (0, 0)
means that the first screen has dimensions 1280 x 1024 and starts in the upper left point (0,0). Next to it is the second screen which upper left point is at coordinate (1280, 0) and its lower right coordinate is at point (3200, 1080) - and they form a rectangle.
What I have to do is draw these screen in an web application - nothing fancy just two different colored rectangles would do. Now, I did a little research and saw that html5 canvas might be the way to go, but I want to hear what you think and maybe give me a push in the right direction. If you could give some jsfiddle example that would be appreciated!
You could just use DIVs with position: absolute, as detailed on this jsFiddle (jQuery used for the sake of simplicity, but the same can easily be accomplished without jQuery).
edit (I just added the code if for some reason your jsfiddle gets deleted!):
HTML:
<div id="screens">
<div id="screen0" class="screen"></div>
<div id="screen1" class="screen"></div>
</div>
CSS:
#screens { position: relative }
.screen {position: absolute }
#screen0 { background: blue; }
#screen1 { background: green; }
JS:
var originalScreens = [
{
position: [0,0],
dimensions: [1280,1024]
},
{
position: [1280,0],
dimensions: [1090,1080]
}
];
var scale = 0.1;
for(var i=0; i<originalScreens.length; i++) {
$('#screen' + i).css('left', (originalScreens[i].position[0] * scale) + 'px');
$('#screen' + i).css('top', (originalScreens[i].position[1] * scale) + 'px');
$('#screen' + i).css('width', (originalScreens[i].dimensions[0] * scale) + 'px');
$('#screen' + i).css('height', (originalScreens[i].dimensions[1] * scale) + 'px');
}
I have an element of an arbitrary type. I'd like to create another element, of either the same or a different type that has the same position and size as the first. The element may or may not be positioned.
For example, I might start with a <select> with a certain size, possibly dependent on its contents, i.e. width/height auto. I want to create a new <div> that appears at the same position and has the same size.
I've tried copying the element's float, clear, position, width, height, margins and padding, but this is a little cumbersome. Also, while it works in Firefox, I'm running into some strange issues when testing on Webkit. Before I spend much more time figuring it out, I'd like to know whether there's some jQuery or jQuery UI functionality that already takes care of what I want to do.
I realize that this question is similar to an existing one, but mine has the important distinction of needing to work with elements of differing types, which precludes clone as a solution.
This is NOT efficient, tested, or complete. And it is probably similar to what you are already doing. But I thought I'd post it anyways:
var positioningProps = ["float","position","width","height","left","top","marginLeft","marginTop","paddingLeft","paddingTop"];
var select = $("#mySelect");
var div = $("<div>").hide().before(select);
// don't do this kind of loop in production code
// http://www.vervestudios.co/jsbench/
for(var i in positioningProps){
div.css(positioningProps[i], select.css(positioningProps[i])||"");
}
select.hide();
How about just copying the element's offset and absolutely positioning it on the page?
Say you had an input element somewhere on the page with dimensions 100x25px.
<input type="text" id="firstname" style="width: 100px; height: 20px" />
And you wanted to place a div right on top of it (and hide the input).
// Store the input in a variable
var $firstname = $("#firstname");
// Create a new div and assign the width/height/top/left properties of the input
var $newdiv = $("<div />").css({
'width': $firstname.width(),
'height': $firstname.height(),
'position': 'absolute',
'top': $firstname.offset().top,
'left': $firstname.offset().left
});
// Add the div to the body
$(body).append($newdiv);
You can find out an elements bounds using this plugin to jQuery. The it would be just a simple matter of setting whatever properties you are interested in to the other object.
http://code.google.com/p/jquery-ui/source/browse/branches/labs/powella/coverslide/res/js/jquery/jquery.bounds.js?r=2698
/*
* jQuery.bounds
* author: Andrew Powell
*/
(function($){
$.fn['bounds'] = function()
{
var t = this, e = t[0];
if (!e) return;
var offset = t.offset(), pos = { width:e.offsetWidth, height:e.offsetHeight, left: 0, top: 0, right: 0, bottom: 0, x: 0, y: 0 };
pos.left = offset.left;
pos.top = offset.top;
//right and bottom
pos.right = (pos.left + pos.width);
pos.bottom = (pos.top + pos.height);
pos.x = pos.left;
pos.y = pos.top;
pos.inner = {width: t.width(), height: t.height()};
$.extend(pos, {toString: function(){ var t = this; return 'x: ' + t.x + ' y: ' + t.y + ' width: ' + t.width + ' height: ' + t.height + ' right: ' + t.right + ' bottom: ' + t.bottom; }});
return pos;
};
})(jQuery);