php+javascript 实现将html元素转换为图片

来源:岁月联盟 编辑:exp 时间:2012-08-04

1,准备要素

1)替换字体的js文件

js代码:

001
function com_stewartspeak_replacement() {
002
/*
003
    Dynamic Heading Generator
004
    By Stewart Rosenberger
005
    http://www.stewartspeak.com/headings/
006
 
007
    This script searches through a web page for specific or general elements
008
    and replaces them with dynamically generated images, in conjunction with
009
    a server-side script.
010
*/
011
 
012
 
013
replaceSelector("h1","dynatext/heading.php",true);//前两个参数需要修改
014
var testURL = "dynatext/loading.gif" ;//修改为对应的图片路径
015
 
016
var doNotPrintImages = false;
017
var printerCSS = "replacement-print.css";
018
 
019
var hideFlicker = false;
020
var hideFlickerCSS = "replacement-screen.css";
021
var hideFlickerTimeout = 100;//这里可以做相应的修改
022
 
023
 
024
 
025
 
026
/* ---------------------------------------------------------------------------
027
    For basic usage, you should not need to edit anything below this comment.
028
    If you need to further customize this script's abilities, make sure
029
    you're familiar with Javascript. And grab a soda or something.
030
*/
031
 
032
var items;
033
var imageLoaded = false;
034
var documentLoaded = false;
035
 
036
function replaceSelector(selector,url,wordwrap)
037
{
038
    if(typeof items == "undefined")
039
        items = new Array();
040
 
041
    items[items.length] = {selector: selector, url: url, wordwrap: wordwrap};
042
}
043
 
044
if(hideFlicker)
045
{     
046
    document.write('<link id="hide-flicker" rel="stylesheet" media="screen" href="' + hideFlickerCSS + '" />');     
047
    window.flickerCheck = function()
048
    {
049
        if(!imageLoaded)
050
            setStyleSheetState('hide-flicker',false);
051
    };
052
    setTimeout('window.flickerCheck();',hideFlickerTimeout)
053
}
054
 
055
if(doNotPrintImages)
056
    document.write('<link id="print-text" rel="stylesheet" media="print" href="' + printerCSS + '" />');
057
 
058
var test = new Image();
059
test.onload = function() { imageLoaded = true; if(documentLoaded) replacement(); };
060
test.src = testURL + "?date=" + (new Date()).getTime();
061
 
062
addLoadHandler(function(){ documentLoaded = true; if(imageLoaded) replacement(); });
063
 
064
 
065
function documentLoad()
066
{
067
    documentLoaded = true;
068
    if(imageLoaded)
069
        replacement();
070
}
071
 
072
function replacement()
073
{
074
    for(var i=0;i<items.length;i++)
075
    {
076
        var elements = getElementsBySelector(items[i].selector);
077
        if(elements.length > 0) for(var j=0;j<elements.length;j++)
078
        {
079
            if(!elements[j])
080
                continue ;
081
        
082
            var text = extractText(elements[j]);
083
            while(elements[j].hasChildNodes())
084
                elements[j].removeChild(elements[j].firstChild);
085
 
086
            var tokens = items[i].wordwrap ? text.split(' ') : [text] ;
087
            for(var k=0;k<tokens.length;k++)
088
            {
089
                var url = items[i].url + "?text="+escape(tokens[k]+' ')+"&selector="+escape(items[i].selector);
090
                var image = document.createElement("img");
091
                image.className = "replacement";
092
                image.alt = tokens[k] ;
093
                image.src = url;
094
                elements[j].appendChild(image);
095
            }
096
 
097
            if(doNotPrintImages)
098
            {
099
                var span = document.createElement("span");
100
                span.style.display = 'none';
101
                span.className = "print-text";
102
                span.appendChild(document.createTextNode(text));
103
                elements[j].appendChild(span);
104
            }
105
        }
106
    }
107
 
108
    if(hideFlicker)
109
        setStyleSheetState('hide-flicker',false);
110
}
111
 
112
function addLoadHandler(handler)
113
{
114
    if(window.addEventListener)
115
    {
116
        window.addEventListener("load",handler,false);
117
    }
118
    else if(window.attachEvent)
119
    {
120
        window.attachEvent("onload",handler);
121
    }
122
    else if(window.onload)
123
    {
124
        var oldHandler = window.onload;
125
        window.onload = function piggyback()
126
        {
127
            oldHandler();
128
            handler();
129
        };
130
    }
131
    else
132
    {
133
        window.onload = handler;
134
    }
135
}
136
 
137
function setStyleSheetState(id,enabled)
138
{
139
    var sheet = document.getElementById(id);
140
    if(sheet)
141
        sheet.disabled = (!enabled);
142
}
143
 
144
function extractText(element)
145
{
146
    if(typeof element == "string")
147
        return element;
148
    else if(typeof element == "undefined")
149
        return element;
150
    else if(element.innerText)
151
        return element.innerText;
152
 
153
    var text = "";
154
    var kids = element.childNodes;
155
    for(var i=0;i<kids.length;i++)
156
    {
157
        if(kids[i].nodeType == 1)
158
        text += extractText(kids[i]);
159
        else if(kids[i].nodeType == 3)
160
        text += kids[i].nodeValue;
161
    }
162
 
163
    return text;
164
}
165
 
166
/*
167
    Finds elements on page that match a given CSS selector rule. Some
168
    complicated rules are not compatible.
169
    Based on Simon Willison's excellent "getElementsBySelector" function.
170
    Original code (with comments and description):
171
        http://simon.incutio.com/archive/2003/03/25/getElementsBySelector
172
*/
173
function getElementsBySelector(selector)
174
{
175
    var tokens = selector.split(' ');
176
    var currentContext = new Array(document);
177
    for(var i=0;i<tokens.length;i++)
178
    {
179
        token = tokens[i].replace(/^/s+/,'').replace(//s+$/,'');
180
        if(token.indexOf('#') > -1)
181
        {
182
            var bits = token.split('#');
183
            var tagName = bits[0];
184
            var id = bits[1];
185
            var element = document.getElementById(id);
186
            if(tagName && element.nodeName.toLowerCase() != tagName)
187
                return new Array();
188
            currentContext = new Array(element);
189
            continue;
190
        }
191
 
192
        if(token.indexOf('.') > -1)
193
        {
194
            var bits = token.split('.');
195
            var tagName = bits[0];
196
            var className = bits[1];
197
            if(!tagName)
198
                tagName = '*';
199
 
200
            var found = new Array;
201
            var foundCount = 0;
202
            for(var h=0;h<currentContext.length;h++)
203
            {
204
                var elements;
205
                if(tagName == '*')
206
                    elements = currentContext[h].all ? currentContext[h].all : currentContext[h].getElementsByTagName('*');
207
                else
208
                    elements = currentContext[h].getElementsByTagName(tagName);
209
 
210
                for(var j=0;j<elements.length;j++)
211
                    found[foundCount++] = elements[j];
212
            }
213
 
214
            currentContext = new Array;
215
            var currentContextIndex = 0;
216
            for(var k=0;k<found.length;k++)
217
            {
218
                if(found[k].className && found[k].className.match(new RegExp('//b'+className+'//b')))
219
                    currentContext[currentContextIndex++] = found[k];
220
            }
221
 
222
            continue;
223
        }
224
 
225
        if(token.match(/^(/w*)/[(/w+)([=~/|/^/$/*]?)=?"?([^/]"]*)"?/]$/))
226
        {
227
            var tagName = RegExp.$1;
228
            var attrName = RegExp.$2;
229
            var attrOperator = RegExp.$3;
230
            var attrValue = RegExp.$4;
231
            if(!tagName)
232
                tagName = '*';
233
 
234
            var found = new Array;
235
            var foundCount = 0;
236
            for(var h=0;h<currentContext.length;h++)
237
            {
238
                var elements;
239
                if(tagName == '*')
240
                    elements = currentContext[h].all ? currentContext[h].all : currentContext[h].getElementsByTagName('*');
241
                else
242
                    elements = currentContext[h].getElementsByTagName(tagName);
243
 
244
                for(var j=0;j<elements.length;j++)
245
                    found[foundCount++] = elements[j];
246
            }
247
 
248
            currentContext = new Array;
249
            var currentContextIndex = 0;
250
            var checkFunction;
251
            switch(attrOperator)
252
            {
253
                case '=':
254
                    checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
255
                    break;
256
                case '~':
257
                    checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('//b'+attrValue+'//b'))); };
258
                    break;
259
                case '|':
260
                    checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
261
                    break;
262
                case '^':
263
                    checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
264
                    break;
265
                case '$':
266
                    checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
267
                    break;
268
                case '*':
269
                    checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
270
                    break;
271
                default :
272
                    checkFunction = function(e) { return e.getAttribute(attrName); };
273
            }
274
 
275
            currentContext = new Array;
276
            var currentContextIndex = 0;
277
            for(var k=0;k<found.length;k++)
278
            {
279
                if(checkFunction(found[k]))
280
                    currentContext[currentContextIndex++] = found[k];
281
            }
282
 
283
            continue;
284
        }
285
 
286
        tagName = token;
287
        var found = new Array;
288
        var foundCount = 0;
289
        for(var h=0;h<currentContext.length;h++)
290
        {
291
            var elements = currentContext[h].getElementsByTagName(tagName);
292
            for(var j=0;j<elements.length; j++)
293
                found[foundCount++] = elements[j];
294
        }
295
 
296
        currentContext = found;
297
    }
298
 
299
    return currentContext;
300
}
301
 
302
 
303
}// end of scope, execute code
304
if(document.createElement && document.getElementsByTagName && !navigator.userAgent.match(/opera//?6/i))
305
    com_stewartspeak_replacement();
2)生成图片的php文件

001
<?php
002
/*
003
    Dynamic Heading Generator
004
    By Stewart Rosenberger
005
    http://www.stewartspeak.com/headings/  
006
 
007
    This script generates PNG images of text, written in
008
    the font/size that you specify. These PNG images are passed
009
    back to the browser. Optionally, they can be cached for later use.
010
    If a cached image is found, a new image will not be generated,
011
    and the existing copy will be sent to the browser.
012
 
013
    Additional documentation on PHP's image handling capabilities can
014
    be found at http://www.php.net/image/  
015
*/
016
 
017
 
018
$font_file  = 'trebuc.ttf' ;//可以做相应的xiuga
019
$font_size  = 23 ;//可以做相应的修改
020
$font_color = '#000000' ;
021
$background_color = '#ffffff' ;
022
$transparent_background  = true ;
023
$cache_images = true ;
024
$cache_folder = 'cache' ;
025
 
026
 
027
 
028
 
029
 
030
 
031
 
032
/*
033
  ---------------------------------------------------------------------------
034
   For basic usage, you should not need to edit anything below this comment.
035
   If you need to further customize this script's abilities, make sure you
036
   are familiar with PHP and its image handling capabilities.
037
  ---------------------------------------------------------------------------
038
*/
039
 
040
$mime_type = 'image/png' ;
041
$extension = '.png' ;
042
$send_buffer_size = 4096 ;
043
 
044
// check for GD support
045
if(!function_exists('ImageCreate'))
046
    fatal_error('Error: Server does not support PHP image generation') ;
047
 
048
// clean up text
049
if(empty($_GET['text']))
050
    fatal_error('Error: No text specified.') ;
051
    
052
$text = $_GET['text'] ;
053
if(get_magic_quotes_gpc())
054
    $text = stripslashes($text) ;
055
$text = javascript_to_html($text) ;
056
 
057
// look for cached copy, send if it exists
058
$hash = md5(basename($font_file) . $font_size . $font_color .
059
            $background_color . $transparent_background . $text) ;
060
$cache_filename = $cache_folder . '/' . $hash . $extension ;
061
if($cache_images && ($file = @fopen($cache_filename,'rb')))
062
{
063
    header('Content-type: ' . $mime_type) ;
064
    while(!feof($file))
065
        print(($buffer = fread($file,$send_buffer_size))) ;
066
    fclose($file) ;
067
    exit ;
068
}
069
 
070
// check font availability
071
$font_found = is_readable($font_file) ;
072
if(!$font_found)
073
{
074
    fatal_error('Error: The server is missing the specified font.') ;
075
}
076
 
077
// create image
078
$background_rgb = hex_to_rgb($background_color) ;
079
$font_rgb = hex_to_rgb($font_color) ;
080
$dip = get_dip($font_file,$font_size) ;
081
$box = @ImageTTFBBox($font_size,0,$font_file,$text) ;
082
$image = @ImageCreate(abs($box[2]-$box[0]),abs($box[5]-$dip)) ;
083
if(!$image || !$box)
084
{
085
    fatal_error('Error: The server could not create this heading image.') ;
086
}
087
 
088
// allocate colors and draw text
089
$background_color = @ImageColorAllocate($image,$background_rgb['red'],
090
    $background_rgb['green'],$background_rgb['blue']) ;
091
$font_color = ImageColorAllocate($image,$font_rgb['red'],
092
    $font_rgb['green'],$font_rgb['blue']) ; 
093
ImageTTFText($image,$font_size,0,-$box[0],abs($box[5]-$box[3])-$box[1],
094
    $font_color,$font_file,$text) ;
095
 
096
// set transparency
097
if($transparent_background)
098
    ImageColorTransparent($image,$background_color) ;
099
 
100
header('Content-type: ' . $mime_type) ;
101
ImagePNG($image) ;
102
 
103
// save copy of image for cache
104
if($cache_images)
105
{
106
    @ImagePNG($image,$cache_filename) ;
107
}
108
 
109
ImageDestroy($image) ;
110
exit ;
111
 
112
 
113
/*
114
    try to determine the "dip" (pixels dropped below baseline) of this
115
    font for this size.
116
*/
117
function get_dip($font,$size)
118
{
119
    $test_chars = 'abcdefghijklmnopqrstuvwxyz' .
120
                  'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
121
                  '1234567890' .
122
                  '!@#$%^&*()/'"///;.,`~<>[]{}-+_-=' ;
123
    $box = @ImageTTFBBox($size,0,$font,$test_chars) ;
124
    return $box[3] ;
125
}
126
 
127
 
128
/*
129
    attempt to create an image containing the error message given.
130
    if this works, the image is sent to the browser. if not, an error
131
    is logged, and passed back to the browser as a 500 code instead.
132
*/
133
function fatal_error($message)
134
{
135
    // send an image
136
    if(function_exists('ImageCreate'))
137
    {
138
        $width = ImageFontWidth(5) * strlen($message) + 10 ;
139
        $height = ImageFontHeight(5) + 10 ;
140
        if($image = ImageCreate($width,$height))
141
        {
142
            $background = ImageColorAllocate($image,255,255,255) ;
143
            $text_color = ImageColorAllocate($image,0,0,0) ;
144
            ImageString($image,5,5,5,$message,$text_color) ;  
145
            header('Content-type: image/png') ;
146
            ImagePNG($image) ;
147
            ImageDestroy($image) ;
148
            exit ;
149
        }
150
    }
151
 
152
    // send 500 code
153
    header("HTTP/1.0 500 Internal Server Error") ;
154
    print($message) ;
155
    exit ;
156
}
157
 
158
 
159
/*
160
    decode an HTML hex-code into an array of R,G, and B values.
161
    accepts these formats: (case insensitive) #ffffff, ffffff, #fff, fff
162
*/  
163
function hex_to_rgb($hex)
164
{
165
    // remove '#'
166
    if(substr($hex,0,1) == '#')
167
        $hex = substr($hex,1) ;
168
 
169
    // expand short form ('fff') color
170
    if(strlen($hex) == 3)
171
    {
172
        $hex = substr($hex,0,1) . substr($hex,0,1) .
173
               substr($hex,1,1) . substr($hex,1,1) .
174
               substr($hex,2,1) . substr($hex,2,1) ;
175
    }
176
 
177
    if(strlen($hex) != 6)
178
        fatal_error('Error: Invalid color "'.$hex.'"') ;
179
 
180
    // convert
181
    $rgb['red'] = hexdec(substr($hex,0,2)) ;
182
    $rgb['green'] = hexdec(substr($hex,2,2)) ;
183
    $rgb['blue'] = hexdec(substr($hex,4,2)) ;
184
 
185
    return $rgb ;
186
}
187
 
188
 
189
/*
190
    convert embedded, javascript unicode characters into embedded HTML
191
    entities. (e.g. '%u2018' => '&#8216;'). returns the converted string.
192
*/
193
function javascript_to_html($text)
194
{
195
    $matches = null ;
196
    preg_match_all('/%u([0-9A-F]{4})/i',$text,$matches) ;
197
    if(!empty($matches)) for($i=0;$i<sizeof($matches[0]);$i++)
198
        $text = str_replace($matches[0][$i],
199
                            '&#'.hexdec($matches[1][$i]).';',$text) ;
200
 
201
    return $text ;
202
}
203
 
204
?>
3)需要的字体

这里将需要的自己放在与js和php文件同在的一个目录下(也可以修改,但是对应文件也要修改)

4)PHP的GD2库

2,实现的html代码

01
<?php
02
//load the popup utils library
03
//require_once 'include/popup_utils.inc.php';
04
?>
05
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
06
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
07
<html>
08
    <head>
09
        <title>
10
            Professional Search Engine Optimization with PHP: Table of Contents
11
        </title>
12
        <script type="text/javascript" language="javascript" src="dynatext/replacement.js"></script>
13
    </head>
14
    <body onload="window.resizeTo(800,600);" onresize='setTimeout("window.resizeTo(800,600);", 100)'>
15
        <h1>
16
            Professional Search Engine Optimization with PHP: Table of Contents
17
        </h1>
18
        <?php
19
            //display popup navigation only when visitor comes from a SERP
20
            // display_navigation();
21
            //display_popup_navigation();
22
        ?>
23
        <ol>
24
            <li>You: Programmer and Search Engine Marketer</li>
25
            <li>A Primer in Basic SEO</li>
26
            <li>Provocative SE-Friendly URLs</li>
27
            <li>Content Relocation and HTTP Status Codes</li>
28
            <li>Duplicate Content</li>
29
            <li>SE-Friendly HTML and JavaScript</li>
30
            <li>Web Syndication and Social Bookmarking</li>
31
            <li>Black Hat SEO</li>
32
            <li>Sitemaps</li>
33
            <li>Link Bait</li>
34
            <li>IP Cloaking, Geo-Targeting, and IP Delivery</li>
35
            <li>Foreign Language SEO</li>
36
            <li>Coping with Technical Issues</li>
37
            <li>Site Clinic: So You Have a Web Site?</li>
38
            <li>WordPress: Creating a SE-Friendly Weblog?</li>
39
            <li>Introduction to Regular Expression</li>
40
        </ol>
41
    </body>
42
</html>
3,使用效果前后对比
使用前

 

使用后

 
作者:张大鹏