How do I animate a strike through effect using JavaScript on a piece of text?
I want to try create an effect where by when I trigger an event an animated line strikes 开发者_如何转开发through a piece of text. The effect should be done in Java Script.
Can someone suggest some ways to do this? I have text already on a page and I would like the text to strike through from left to right as if a line is being drawn
Using jQuery it's possible with little tweak: http://jsfiddle.net/yahavbr/EbNh7/
JS in use:
var _text = "";
$(document).ready(function() {
_text = $("#myDiv").text();
StrikeThrough(0);
});
function StrikeThrough(index) {
if (index >= _text.length)
return false;
var sToStrike = _text.substr(0, index + 1);
var sAfter = (index < (_text.length - 1)) ? _text.substr(index + 1, _text.length - index) : "";
$("#myDiv").html("<strike>" + sToStrike + "</strike>" + sAfter);
window.setTimeout(function() {
StrikeThrough(index + 1);
}, 100);
}
This will strike through myDiv
text, making the line appear with animation.
As it's not using any heavy jQuery stuff it can be converted to plain JavaScript pretty easily so if you prefer not to use jQuery I'll edit my answer.
var findText = function(element, pattern, callback) {
if ( ! element.childNodes) {
return;
}
for (var childi = element.childNodes.length; childi-- > 0;) {
var child = element.childNodes[childi];
if (child.nodeType == 1) {
findText(child, pattern, callback);
} else if (child.nodeType == 3) {
var matches = [];
var match;
while (match = pattern.exec(child.data))
matches.push(match);
for (var i = matches.length; i-- > 0;)
callback.call(window, child, matches[i]);
}
}
}
findText(document.body, /./g, function(node, match) {
var element = document.createElement('span');
node.splitText(match.index + 1);
element.appendChild(node.splitText(match.index));
node.parentNode.insertBefore(element, node.nextSibling);
});
var spans = document.getElementsByTagName('span'),
spansLength = spans.length,
currentSpan = 0,
interval = setInterval(function() {
if (currentSpan == spansLength) {
clearInterval(interval);
}
spans[currentSpan++].style.textDecoration = 'line-through';
}, 100);
jsFiddle.
- Go through each character (except
\n
) using regex and recursively apply function with callback to wrap each individual matched character with aspan
. - Select all these
span
elements and then usesetInterval()
to traverse them, addingstyle="text-decoration: line-through
via thestyle
object of thespan
. - Stop when we have iterated through each
span
.
The disadvantage of using innerHTML
is when you serialize the HTML, you lose all events, etc. In the fiddle above, the strong
element is still clickable (you will click the span
, which will bubble up to the parent).
You could use jQuery to animate a background image that looks like a strikethrough. Perhaps something like this:
$(".someclass").animate({backgroundPosition: '0px 0px'})
This might look a little smoother than trying to do something involving <s>
tags. Your HTML markup would be like this:
<span class="someclass">Lorem ipsum</span>
And you'd need to make sure that .someclass
had default CSS that hid the background image by using background-position, ie:
.someclass { background-position: -1000px 0px; }
I would create an empty span before the piece of text with a strikethrough style on it. Then, I would write a function that pops the first character off the front of the piece of text and appends it to your span. Then, use setTimeout() to call that function repeatedly until the piece of text is empty.
You asked for a suggestion - code would take longer :)
Just came here from google, ended up writing my own simple little function. This is how I did it:
function drawLineOnClick() {
//add or prepend div to the top of the div holding your text
$("#IdOfElementHoldingTheText").prepend('<div id="lineThrough"></div>');
var WidthStrikeThrEl = $("#IdOfElementHoldingTheText").width();
$("#lineThrough").animate({width: WidthStrikeThrEl},1000, function() {
//when line has been drawn, apply CSS line-through and remove line
$("#IdOfElementHoldingTheText").attr('class', 'lineThrCssClass');
$("#lineThrough").remove();
});
}
#lineThrough {
position:absolute;
top:23px; //centering line over text to simulate actual line through
width:0px;
height:1px;
background:#444; //color of line through
}
.lineThrCssClass {
color:#444;
text-decoration:line-through;
}
You could add an <s>
tag to the beginning of the string and iteratively move the closing </s>
tag one character further towards the end of the string, probably best using setTimeout()
.
Something along these lines (not tested):
STRIKE_POS = 1;
ORIG_STR = '';
function startStrike(str) {
STRIKE_POS = 1;
ORIG_STR = str;
strike();
}
function strike() {
var str = '<s>' + ORIG_STR.substr(0, STRIKE_POS) + '</s>'
+ ORIG_STR.substr(STRIKE_POS);
// DO SOMETHING WITH THE STRING, LIKE DISPLAY SOMEWHERE
STRIKE_POS++;
if (STRIKE_POS < ORIG_STR.length) {
window.setTimeout("strike()", 200); // adjust the timeout
}
}
Here's a basic implementation that works in current versions of IE, Firefox and Chrome:
<html>
<head>
<script type="text/javascript">
window.gradualStrike = function(spanId, timeMillis) {
var stepDuration;
var strikeElem = document.getElementById(spanId);
var strikeText = strikeElem.innerHTML.replace("<S>", "<s>").replace("</S>", "</s>"); //IE uppercases the tag
var currentStrikePos = strikeText.indexOf("</s>");
if (currentStrikePos < 0) {
currentStrikePos = 0;
stepDuration = timeMillis / strikeText.length;
}
else {
if (currentStrikePos + 3 == strikeText.length) {
//the '</s>' is at the end, we are done
return;
}
currentStrikePos -= 3; //account for the '<s>' tag
stepDuration = timeMillis / (strikeText.length - 7); //account for '<s>' and '</s>'
strikeText = strikeText.replace("<s>", "").replace("</s>", ""); //strikeText.replace(/\<s\>/, "").replace(/\<\/s\>/, "");
}
currentStrikePos++;
strikeText = "<s>" + strikeText.substring(0, currentStrikePos) + "</s>" + strikeText.substring(currentStrikePos);
strikeElem.innerHTML = strikeText;
setTimeout("gradualStrike('" + spanId + "', " + timeMillis + ");", stepDuration);
};
</script>
</head>
<body>
<span id="someText" onclick="gradualStrike('someText', 1000); this.onclick=function(){return;};">Click to strike...</span>
</body>
</html>
精彩评论