php+javascript 实现将html元素转换为图片
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' => '‘'). 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,使用效果前后对比
使用前
使用后
作者:张大鹏