开发者

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 a span.
  • Select all these span elements and then use setInterval() to traverse them, adding style="text-decoration: line-through via the style object of the span.
  • 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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜