深入PHP许愿墙模块功能分析


Posted in PHP onJune 25, 2013

许愿墙模块功能分析
一,热点技术
1,实现可拖放DOM技术移动许愿字条
可拖放DOM模式(Draggable DOM pattern)的宗旨在于允许浏览者自己定义页面中各元素的位置,并且,只需要用鼠标选中要移动的部分,把它拖到新的位置上,就可以定制页面。

DOM是Document Object Model文档对象模型的缩写,是一种与浏览器、平台、语言无关的接口,使用户可以访问页面其他的标准组件。DOM是以层次结构组织的节点或信息片段的集合。这个层次结构允许开发人员在树中导航寻找特定信息。分析该结构通常需要加载整个文档的构造层次结构,然后才能做任何工作。由于它基于信息层次,因此DOM被认为基于树或基于对象。
具体实现时以下时间会被触发:
(1)moveStart
(2)Move
(3)moveEnd
当按下鼠标左键,开始移动鼠标时,在被拖动的许愿条上就会触发moveStart事件。用户可以使用moveStart事件处理函数在拖动开始时允许javaScript代码。当moveStart事件被触发后,Move时间会一直触发,只要对象还在被拖动,就一直触发。当拖动停止时,则触发moveEnd事件。
echo输出许愿条样式布局,代码如下:

echo "
 <DIV class='".$pagecolor."'style='left:".$L."px;top:".$T."px;z-index:".$Z."' id='".$id."' onmousedown='Move(this,event)' ondblclick=Show(".$id.",'shadeDiv')>      
  <TABLE cellSpacing=0 cellPadding=0 border=0>
   <TBODY>
    <TR>
     <TD>
       <DIV class=shead>
         <span class='Num' >爱墙编号:".$id."   ".$sendtime." <a onclick='myClose(".$id.")'>×</span>
      </DIV>
     </TD>
    </TR>
    <TR>
     <TD>
       <DIV class=sbody><img src='".$face."' id='IconImg' style='float:left'>
        <span id='PickerSample'>".$Picker."</span><br>    <span id='ContentSample'>$content</span>
      </DIV>
       <DIV class=sbody >
       <H2><span id='authorSample'>".$author."</span></H2>
      </DIV>
      <DIV class=sbot align='right'>
       <br><a href='#' onclick='holdout(".$id.",".$hits.")''>[祝福你]</a> 福气:<span id='fq_id".$id."'>".$hits."</span> <span id='QQSample'>QQ:<a href='http://wpa.qq.com/msgrd?uin=".$QQ."&Site=1&Menu=yes' title='单击与他/她交谈' target='_blank'>".$QQ."</a></span>
      </DIV>
     </TD>
    </TR>
   </TBODY>
  </TABLE>
 </DIV>";

当按下鼠标左键时,应用鼠标时间onmousedown触发Move()函数
var Layer='';
document.onmouseup=moveEnd;
document.onmousemove=moveStart;
var b;
var c;
function Move(Object,event){ //移动DIV许愿字条
 Layer=Object.id;
 if(document.all){
  document.getElementById(Layer).setCapture();
  b=event.x-document.getElementById(Layer).style.pixelLeft; //设置左边框
  c=event.y-document.getElementById(Layer).style.pixelTop; //设置右边框
 }else if(window.captureEvents){
  window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
  b=event.layerX;  //返回时间对象相对于本体的横坐标
  c=event.layerY;  //返回时间对象相对于本体的纵坐标
 }
 /**实现鼠标单击字条时,字条置上**/
  document.getElementById(Layer).style.zIndex=iLayerMaxNum;
  iLayerMaxNum=iLayerMaxNum+1;
 /********************************/
}

document.all是文档中所有标签组成的一个数组变量,包括了文档对象中的所有元素,这个数组可以访问文档中的所有元素。
语法:
document.all[i]
document.all[name]
document.all.tags[tagname]
说明:
all[]是一个多功能的类似数组的对象,它提供了对文档中所有HTML元素的访问。all[]数组源自于IE4并已经被很多其他浏览器采用

all[]已经被Document接口的标准的getElementById()方法和getElementByTagName()方法以及Document对象的getElementByName()方法所取代。

all[]包含的元素保存了最初的顺序,如果你知道他们在数组中的确切数字化位置,可以直接从数组中提取他们。然而,更为常见的是使用all[]数组,根据他们的HTML属性name或id来访问元素。如果元素拥有指定的name,将得到共享同一名称的元素的一个数组。
document.all可以判断浏览器是否是IE

 if(document.all){
  alert("is IE!");
 }

window.captureEvents()
window.captureEvents(event1 | event2 | eventN)
captureEvents()方法捕获所有发生的事件类型,如果有多个事件发生,则用|竖线隔开;captureEvents()方法主要事件如下:
Event.ABORT
Event.BLUR
Event.CHANGE
Event.CLICK
Event.DBLCLICK
Event.DRAGDROP
Event.ERROR
Event.FOCUS
Event.KEYDOWN
Event.KEYPRESS
Event.KEYUP
Event.LOAD
Event.MOUSEDOWN
Event.MOUSEMOVE
Event.MOUSEOUT
Event.MOUSEOVER
Event.MOUSEUP
Event.MOVE
Event.RESET
Event.RESIZE
Event.SELECT
Event.SUBMIT
Event.UNLOAD
示例代码:
<html>
    <head>
    <title>Using window.captureEvents</title>
    <script language="JavaScript1.2">
    <!--
    var counter = 0;
    window.captureEvents(Event.CLICK)
    window.onclick = myClickHandler;
    function myClickHandler(){
  window.document.myForm.myText.handleEvent;
    }
    function changeText(){
  document.myForm.myText.value = counter++;
    }
    -->
    </script>
    </head>
    <body>
    <form name="myForm">
  <input type=TEXT size=2 value="" name="myText" onClick='changeText()'>
    </form>
    </body>
</html>

当鼠标移动时,触发moveStart()函数,代码如下:
function moveStart(d){
 if(Layer!=''){  //如果图层不为空
  if(document.all){
   document.getElementById(Layer).style.left=event.x-b; //设置左边距
   document.getElementById(Layer).style.top=event.y-c;  //设置右边距
  }else if(window.captureEvents){
   document.getElementById(Layer).style.left=(d.clientX-b)+"px";
   document.getElementById(Layer).style.top=(d.clientY-c)+"px";
  }
 }
}

应用DOM方法(document对象的getElementById方法)获取包含许愿字条layer层左边距和上边距的距离。b和c分别表示获取Layer层的横纵坐标。
clientX:检索与窗口客户区域有关的鼠标坐标的x坐标,属性为只读,没有默认值。
clientY:检索与窗口客户区域有关的鼠标光标的y坐标,属性为只读,没有默认值。
clientX,pageX,offsetX,x,layerX,screenX,offsetLeft各浏览器通用属性:
screenX:
鼠标在显示屏幕上的坐标。
clientX:鼠标在页面显示区域的坐标。

特有属性:(
注:IE和FF的定位有个1px的差别,实际上,IE的定位从0开始,FF的定位从1开始,FF永远会比IE大1px,需要根据实际情况处理。)
pageX:FF特有,鼠标在页面上的位置,从页面左上角开始定位,这个可以很方便在整个页面上进行定位,IE没有直接替换的属性。

layerX:FF特有,鼠标相对于“触发事件的元素的层级关系中离该元素最近的,设置了position的父元素”的边界的位置,从border的左上角开始定位,即如果这个父元素存在border,则坐标原点在border的左上角,而不是内容区域的左上角。

offsetX:IE特有,鼠标相对于“触发事件的元素”的位置,从内容区域左上角开始定位,不是从border左上角开始!这个属性比较好用,用来判断鼠标点在一个元素中的哪个位置很方便,FF没有直接替换的属性。

x:
IE特有,跟layerX一个效果,可作为layerX的直接替换属性。

offsetLeft:这个属性不是事件对象的属性,而是DOM对象所有的,该属性表示的是DOM对象在“该DOM对象的层级关系中离该对象最近的,设置了position的父对象”中的位置,虽然话是这么说的,但是不同的浏览器效果不一样,FF中严格按上述说明执行,但是在IE6/7中,这个属性返回该DOM对象在其直接父对象中的位置,但是IE8改正了这个问题,不过IE8又有了一个新问题,其他的浏览器都是从父对象的内容区域的左上角开始定位,IE8确是从父元素的border的左上角开始定位,由于测试环境为IETester中的IE8,不能排除是IETester的问题。
当鼠标抬起时,触发moveEnd()函数,代码如下:

function moveEnd(d){
 if(Layer!=''){  //如果layer图层不为空
  if(document.all){
   document.getElementById(Layer).releaseCapture();
   Layer=''; //将layer图层设为空
  }else if(window.captureEvents){
   window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
   Layer=''; //将layer图层设为空
  }
 }
}

在上面的代码中,setCapture()函数的作用是将后续的mouse事件都发送给这个对象,releaseCapture()函数是将mouse事件返回,由document、window等对象来自行处理,这样就保证了在拖动的过程中,不会由于经过了其他元素而受到干扰。另外,还有一个很重要的因素,在win32上,MOUSEMOVE的时间不是连续的,并不是每次移动一个像素的鼠标指针,就会发生一个MOUSEMOVE事件,Windows会周期性检测鼠标指针的位置变化来产生MOUSEMOVE的事件。所以,如果是一个很小的页面对象,例如一个直径5像素的圆点,如果没有setCapture和releaseCapture,那么在按住鼠标之后,快速地移动鼠标,就有可能鼠标移动走了但小圆点还在原地,就是因为下一次的mousemove事件已经不再发给这个圆点对象了。

2,对QQ号文本框中禁止非数字字符输入
在动态网站中,为了确保用户输入的文本或数值的有效性,必须对用户输入的数据加以验证,确保数据的准确及安全性。本模块禁止用户向QQ文本框中输入汉字或英文字符。

<input name="QQ" type="text" id="QQ" 
<SPAN style="WHITE-SPACE: pre"> </SPAN>onKeyUp="setQQ();if(/(^0+)/.test(value))value=value.replace(/^0*/, '')"  
<SPAN style="WHITE-SPACE: pre"> </SPAN>onKeyDown="setQQ();"    //键盘按下时触发,比如按着1不放时,该函数生效
<SPAN style="WHITE-SPACE: pre"> </SPAN>onKeyPress="return event.keyCode>=48 && event.keyCode<=57;" size="16" maxlength="10" 
<SPAN style="WHITE-SPACE: pre"> </SPAN>onpaste="var s=clipboardData.getData('text'); if(!/\D/.test(s))value=s.replace(/^0*/,''); 
<SPAN style="WHITE-SPACE: pre"> </SPAN>return false;"
/>

上面代码中,分别应用3个事件来控制QQ号输入的值。
onKeyUp事件:事件会在键盘按键被松开时发生。如果是数字则可以添加到QQ号文本框中。
onKeyPress事件:事件会在键盘按键被按下并释放一个键时发生。只允许用户输入0~9之间的数字。
onpaste事件:当用户粘贴数据以便从系统剪切板向文档传送数据时在目标对象上触发。当用户向QQ号文本框中粘贴字符串时,只允许用户粘贴数字串。
另外,应用isNaN()方法来验证输入的QQ号是否是数值型。
isNaN(num Value);
numvalue:是必选项,用来检查是否为NaN的值。
当提交签字许愿字条时,将触发checkForm()函数,应用document.getElementById()函数和表单字段的ID(QQ文本框的ID号为“QQ”)来直接获取这个元素。应用isNaN()方法来验证QQ号是否为数值型。
function checkForm(){         //祝福内容
 if(isNaN(document.getElementById('QQ').value)){
  alert('您输入的QQ号不是数值型,请重新输入!');
  document.getElementById('QQ').focus();
  return false; 
 }
}

常用文本框限制代码:
代码示例:
onkeyup="value=value.replace(/[^a-zA-Z]/g,'')"
说明:
replace(/[^a-zA-Z]/g,'')
其中有^为逻辑词“非”,然后后面跟着a-zA-Z指的是英文字母大小写范围,“/g”表示用后面的''中的字符(当前为空)全局替换。
此句代码的含义为:在文本框中只能输入大写或小写字母,如果不是,则自动删除。
常用输入限制代码:
只能输入英文字母:
 <input type="text" onkeyup="value=value.replace(/[^a-zA-Z]/g,'')"/>

只能输入英文和数字:
 <input type="text" onkeyup="value=value.replace(/[^0-9a-zA-Z]/g,'')"/>
 <input type="text" onkeyup="value=value.replace(/[\W]/g,'')"/>     \W匹配字母或数字或下划线或汉字,\D表示匹配数字

只能输入数字和x(用于身份证号的输入) :
 <input type="text" onKeyUp="value=value.replace(/[^\d|x]/g,'')" />   |后面的就是可以排除的非数字,可是一个范围x-z

只能输入数字
 <input type="text" onKeyUp="value=value.replace(/[^\d]/g,'')" />  \D表示匹配数字,中文输入法输入时,存在后续表格不能输入中文问题
 <input type="text" onKeypress="if(event.keyCode < 45 || event.keyCode >57) event.returnValue = false;">  不能输入字母,但能输入/.-等
 <INPUT TYPE="text" onkeyup="this.value=this.value.replace(/[^\d]/g,'')" onpaste="return false">  不能输入数字,不允许粘贴
 <input name=txt1 onchange="if(/\D/.test(this.value)){alert('只能输入数字');this.value='';}"> 
 <input onkeyup="if(isNaN(value))execCommand('undo')" onafterpaste="if(isNaN(value)) execCommand('undo')"> 但可以输入空格,解决中文输入法问题

只能输入字母和汉字(还有一些非数字字符)
 <input onkeyup="value=value.replace(/[\d]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[\d]/g,''))">

小数点后只能有最多两位(数字,中文都可输入),不能输入字母和运算符号
 <input onKeyPress="if((event.keyCode<48 || event.keyCode>57) && event.keyCode!=46 || /\.\d\d$/.test(value))event.returnValue=false">

3,限制纸条内容的长度
在签写许愿内容时,通常需要限制用户输入文本的长度。在字符串长度的计算上,汉字是占两个字符(汉字的宽度以及存储所占的位置决定了一个汉字占两个字符),而英文字母和数字都被识别为一个字符。在PHP中获取字符串长度应用strlen()函数实现。但是在本模块中,为了能够实现统计许愿内容所允许输入的剩余字符数,这里就要重新输写计算中英文数字混合字符串长度的函数。在签写许愿内容时,实时限制字符数。
添加一个文本框,用来控制输入祝福纸条内容剩余的字节数。
<INPUT style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" readOnly maxLength=3 size=3 value=150 name=freeLength>

在上面的代码中,应用“freeLength”来实时输出祝福纸条内容所剩余的字符数。
添加一个编辑框用来输入祝福纸条的内容,添加onkeydown和onkeyup事件来触发javascript脚本自定义的函数textCounter(),用来限制该编辑输入的字符数,最多输入150个字符,如果许愿内容大于150,则自动删除,仅保留最大容量值。
<textarea name="content" id="content" cols="66" rows="6" 
 onkeydown="textCounter(this.form.content,this.form.freeLength,150)"  
 onkeyup="textCounter(this.form.content,this.form.freeLength,150)" 
 onafterpaste="textCounter(this.form.content,this.form.freeLength,150)">
</textarea>

在上面的代码中,textCounter()函数有3个参数值,第一个参数值“this.form.content”是指输入的许愿内容;第二个参数值“this.form.freeLength”是指允许输入的许愿内容字符数;第三个参数“150”是输入许愿内容的最大容量值。

应用javascript脚本自定义一个函数textCounter(),控制祝福内容不能超过150个字符,这里需要注意的是,中英文所占的字节数不同。

DBCS是亚洲的字符集,包含ANSI(ANSI即ASCII码值为0~255之间的字符)。DBCS使用1个或者2个字节来表示一个字符集,超过256个字符则占用两个字节。当字符为ANSI时,存放于文件中只占用1个字节。如果非ANSI(大于256个字符),则占用两个字节。因此,这里就用三目运算符来分别计算英文数字和汉字所占用的字节数。当变量StrValue.charCodeAt(i)小于等于256时,按1个字节计算;大于256时按2个字节计算。

function textCounter(field, countfield, maxlimit) {  //祝福内容限制在120个字符内
  var StrValue  = field.value;
   var ByteCount = 0;
 var StrLength = field.value.length;
 for (i=0;i<StrLength;i++){   //记算祝福文字个数,英文数字占1个字符,汉字占2个字
  ByteCount = (StrValue.charCodeAt(i)<=256) ? ByteCount + 1 : ByteCount + 2;
 }
 if(ByteCount<=maxlimit){
  strtemp=StrValue;
  document.getElementById('ContentSample').innerHTML = StrValue;
  countfield.value = maxlimit - ByteCount;
 }else{
  document.getElementById('content').innerHTML = strtemp;
 }
}

该函数只能限制显示部分150字节,但是输入框没有现在,而且粘贴超过150字节时,显示为空白。修改代码如下:
function textCounter(field, countfield, maxlimit) {  //祝福内容限制在150个字符内
  var StrValue  = field.value;
   var ByteCount = 0;
 var StrLength = field.value.length;
 var cutstr = '';
 for (i=0;i<StrLength;i++){   
  ByteCount = (StrValue.charCodeAt(i)<=256) ? ByteCount + 1 : ByteCount + 2; //记算祝福文字个数,英文数字占1个字符,汉字占2个字
        if( ByteCount<=maxlimit){
   cutstr = StrValue.substring(0,i+1); //如果输入字符小于限制长度,截取当前输入字符i+1为输入字符个数
   strtemp = cutstr; 
        } else {
   cutstr=strtemp;  //否则截取最大输入字符长度
  }
 }
 if(ByteCount<=maxlimit){
  document.getElementById('ContentSample').innerHTML = cutstr;  //输出显示内容
  countfield.value = maxlimit - ByteCount;
 }else{
  document.getElementById('content').value = cutstr;  //限制输入框显示内容
  document.getElementById('ContentSample').innerHTML = cutstr;  //输出显示内容
  countfield.value =0; //剩余字节数
 }
}

在上面的代码中,“countfield.value”是用来计算输入字符串剩余的字符数,并将该值赋给textCounter()函数的第2个参数值“this.form.freeLength”,以此来实时计算当前许愿内容所允许输入的字符数量。

4,PHP验证码类当前页面校验验证码输入对与错
当前页面验证输入是否正确的方法Ajax,add.js

function codecheck(){
 var getVcode = document.getElementById('checkcode').value; //获取验证码输入框的内容
 xmlhttp.open("get","codeChk.php?code="+getVcode,true);   //将验证码发送到codeChk.php页面检验验证码是否正确
 xmlhttp.onreadystatechange=function(){ 
  if(xmlhttp.readyState==4)
  {
   if(xmlhttp.status==200)
   {
    var msg=xmlhttp.responseText;
    if(msg==1){
     document.getElementById("messageImg").src="images/dui.gif"; //验证码正确,输出显示正确图片
     document.getElementById('txt_hyan').value = getVcode; 
    }else{
     document.getElementById("messageImg").src="images/cuo.gif"; //验证码错误,输出显示错误图片
     document.getElementById('checkcode').focus();
     return false;
    }
   }
  }
 }
 xmlhttp.send(null);
}

codeChk.php验证码检验页面
<?php  
 session_start();
 require 'secoder.class.php';  //先把类包含进来,实际路径根据实际情况进行修改。  
 $vcode = new YL_Security_Secoder();      //实例化一个对象  
 $code = $_GET['code']; 
 echo $vcode->check($code);  //check($code)函数返回的是true或者false,返回true时,codeChk.php页面输出的是1,否则没有输出     
?>

secoder.class.php验证码类中的check($code)函数
public static function check($code) {
 isset($_SESSION) || session_start();
 // 验证码不能为空
 if(empty($code) || empty($_SESSION[self::$seKey])) {
  return false; }
 // session 过期
 if(time() - $_SESSION[self::$seKey]['time'] > self::$expire) {
  unset($_SESSION[self::$seKey]);
  return false;
 }
 if(strtoupper($code) == $_SESSION[self::$seKey]['code']) {  //不区分大小写比较
  return true;  
 }
 return false;
}

5,定义生成指定范围的许愿条随机算法
本模块需要生成一个指定范围的随机算法,用来显示许愿字条的显示位置,以使每次展示在读者眼前的都是不同的许愿字条。本模块主要应用rand()函数控制许愿墙纸的显示位置。
rand()函数用于产生一个随机整数
语法:rand(min,max)
参数:min,max可选,规定随机数产生的范围
如果没有提供可选参数 min 和 max,rand() 返回 0 到 RAND_MAX 之间的伪随机整数。在某些平台下(例如 Windows)RAND_MAX 只有 32768。如果需要的范围大于 32768,那么指定 min 和 max 参数就可以生成大于 RAND_MAX 的数了,或者考虑用 mt_rand() 来替代它。
mt_rand() 使用 Mersenne Twister 算法返回随机整数
语法:mt_rand(min,max)
如果没有提供可选参数 min 和 max,mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数。很多老的libc的随机数发生器具有一些不确定和未知的特性而且很慢。php的rand()函数默认使用libc随机数发生器。mt_rand()函数是非正式用来替换它的。该函数用了Mersenne Twister中已知的特性作为随机数发生器,它可以产生随机数值的平均速度比libc提供的rand()快四倍。
随机显示许愿墙纸的关键代码如下:
$T=rand(320,520);
$L=rand(5,790); 
$Z=$page_count;
$Z = $Z - 3;
echo "
 <DIV class='".$pagecolor."'style='left:".$L."px;top:".$T."px;z-index:".$Z.";' id='".$id."' onmousedown='Move(this,event)' ondblclick=Show(".$id.",'shadeDiv')>      
  <TABLE cellSpacing=0 cellPadding=0 border=0>
   <TBODY>
    <TR>
     <TD>
       <DIV class=shead>
         <span class='Num' >爱墙编号:".$id."   ".$sendtime." <a onclick='myClose(".$id.")'>×</span>
      </DIV>
     </TD>
    </TR>
    <TR>
     <TD>
       <DIV class=sbody><img src='".$face."' id='IconImg' style='float:left'>
        <span id='PickerSample'>".$Picker."</span><br>    <span id='ContentSample'>$content</span>
      </DIV>
       <DIV class=sbody >
       <H2><span id='authorSample'>".$author."</span></H2>
      </DIV>
      <DIV class=sbot align='right'>
       <br><a href='#' onclick='holdout(".$id.",".$hits.")''>[祝福你]</a> 福气:<span id='fq_id".$id."'>".$hits."</span> <span id='QQSample'>QQ:<a href='http://wpa.qq.com/msgrd?uin=".$QQ."&Site=1&Menu=yes' title='单击与他/她交谈' target='_blank'>".$QQ."</a></span>
      </DIV>
     </TD>
    </TR>
   </TBODY>
  </TABLE>
 </DIV>";

6,解析IP获取用户所在城市
在PHP中,使用PHP预定义变量$_SERVER['REMOTE_ADDR']获取客户端的IP地址。然后将IP按照通用的算法将其解析成一个数字串(每个城市都有一个对应的数字串),通过这个数字串来确定查询用户所在的城市名称。
在数据库中,IP区域的存储时一个数字串,并非实际的IP地址,这时就需要对客户端或服务器端的IP转换成指定数字串的格式,从而进行地域信息的查询。
$ip=getenv('REMOTE_ADDR');   //获取客户端IP地址
/********解释IP区域***********/
$cip=cip($ip);
$csql="select * from tb_ip where (ip1<'".$cip."' and  ip2>'".$cip."') or (ip1=ip2 and ip2='".$cip."')";
//执行查询
$res = $DB->fetch_one_array($csql);
$cip1=$res['country'];
if($cip1==""){
 $cip1="IP不详";
}

二,实现过程
1,双击许愿字条,该字条置顶显示,并屏蔽整个页面
当用户双击许愿字条后,该许愿字条将置顶显示,同时屏蔽整个页面,以达到突出显示的效果。
(1)控制DIV突显效果,首页设置一个隐藏的DIV,ID名称为“shadeDiv”,代码如下
<div style="display:none;" id="shadeDiv" onclick="Hide();"></div>
(2)应用Javascript脚本自定义一个Hide()函数,通过设置DIV的显示属性display设置为空,从而隐藏DIV,代码如下:
function Hide(){
 document.getElementById("shadeDiv").style.display = "none";
 iLayerMaxNum = iLayerMaxNum+2;
}

(3)在CSS样式表中设置隐藏DIV的样式。代码如下:
#shadeDiv{filter:alpha(Opacity=55);opacity:0.35;background: #333;position:absolute;} //IE浏览器下滤镜效果,兼容性不好
(4)接下来,双击已经设计好的许愿字条DIV图层,代码如下:
ondblclick=Show(".$id.",'shadeDiv')
(5)自定义一个函数show(),用来控制背景的效果。
function Show(n,divName){
 document.getElementById(n).style.zIndex = iLayerMaxNum+1;
 document.getElementById(divName).style.display = "block";
 document.getElementById(divName).style.zIndex = iLayerMaxNum;
 var size = getPageSize(); //设置隐藏区域的面积,这里是获取许愿墙显示区域的面积,即本例中设置滤镜的面积
 document.getElementById(divName).style.width = size[0]+"px"; 
 document.getElementById(divName).style.height = size[1]+"px";
}

(6)设置纸条显示的区域,这里得到的仅仅是数字
function getPageSize(){
 var w =document.body.clientWidth;
 var h= document.body.clientHeight;
 arrayPageSize = new Array(w,h); 
 return arrayPageSize;
}

2,应用Jpgraph图形类库实现3D饼形图表按地域统计分析许愿比率,实现过程如下:
(1)应用浮动框架技术实现不同类别下的地域统计分析结果,每一个黄颜色的版块分别是一个浮动框架.浮动框架布局的代码如下:
<!----------------------------应用3D饼形图按地域统计分析”全部“许愿的比率---------------------------->
<div align="center">
    <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_all.php" style="HEIGHT:290px;VISIBILITY:inherit;WIDTH:1004px;Z-INDEX:3"> 
    </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”亲情类“许愿的比率---------------------------->
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_relative.php" style="VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX:3"> 
    </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”爱情类“许愿的比率----------------------------> 
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_love.php"    style="HEIGHT:90px;VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX: 3"> 
    </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”友情类“许愿的比率---------------------------->
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_friend.php" style="VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX:3"> 
 </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”自己类“许愿的比率---------------------------->
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_self.php" style="VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX:3"> 
 </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”奥运会类“许愿的比率---------------------------->
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_olympic.php" style="VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX:3"> 
 </IFRAME>
</div>
<!----------------------------应用3D饼形图按地域统计分析”汶川类“许愿的比率---------------------------->
<div align="center">
 <IFRAME frameBorder=0 id=top name=top scrolling=no src="statistic_wch.php" style="VISIBILITY:inherit;WIDTH:330px;height:260px;Z-INDEX:3"> 
 </IFRAME>
</div>

(2)应用3D饼形图动态统计分析全部区域的许愿比率
首先应用Jpgraph类库实现图表分析,需要应用include语句引用jpgraph.php文件。代码如下:
<?php
 include("global.php");  //链接数据库源文件
 include("jpgraph/jpgraph.php");  //引用图表分析类文件
?>

绘制饼形图需要引用jpgraph_pie.php文件。绘制3D效果的饼形图需要创建PiePlot3D类对象,PiePlot3D类在Jpgraph_pie3d.php中定义,需要应用include语句调用该文件。代码如下:
<?php
 include("jpgraph/jpgraph_pie.php");  //引用饼形图类文件
 include_once("jpgraph/jpgraph_pie3d.php");  //引用3D饼图PiePlot3D对象所在的类文件
?>

创建graph对象,生成一个990x276像素大小的画布,设置统计图所在画布的位置以及画布的阴影。设置标题的字体以及图例的字体。设置饼形图所在画布的位置以及半径,将绘制的3D饼形图添加到图像中。
<?php
$graph = new PieGraph(990,276); //创建画布
$graph->SetShadow(); //设置阴影
$graph->title->Set("应用3D饼形图统计分析全部区域许愿比率"); //设置标题名称
$graph->title->SetFont(FF_SIMSUN,FS_BOLD); //设置标题的字体加粗
$graph->legend->SetFont(FF_SIMSUN,FS_NORMAL); //设置饼形图文字的字体
$size=0.5; //设置饼形图的半径
/***********************统计全部许愿比率*************************/
//创建饼形图对象
$p0= new PiePlot3D($arraynum0); //创建饼形图对象
$p0->SetLegends($arraycip0); 
$p0->SetSize($size); //设置饼形图的大小
$p0->SetCenter(0.45,0.48); //设置饼形图的坐标位置
$p0->SetLegends($arraycip0); //设置城市名称
$p0->value->SetFont(FF_FONT0); //设置字体
$p0->title->SetFont(FF_SIMSUN,FS_BOLD);  //设置标题字体加粗
/*************************************************************/
$graph->Add($p0);  //添加3D饼形图到图像中
$graph->Stroke(); //输出图像
?>

(3)应用3D饼形图动态统计分析”亲情类“的许愿比率。其实现方法与获取全部的许愿比率的方法基本类似,不同的是这里在检索亲情类许愿人数时设置了where查询条件。另外在设置饼形图的半径和位置上稍微有变化。
<?php
include("global.php"); //链接数据库文件
include ("jpgraph/jpgraph.php"); //引用图表分析类文件
include ("jpgraph/jpgraph_pie.php"); //引用饼形图类文件
include_once ("jpgraph/jpgraph_pie3d.php");  //引用3D饼图PiePlot3D对象所在的类文件
/***********************统计亲情类别*************************/
$sql2="select distinct(count(cip)) as num,cip from tb_wishes where wishsort='亲情' group by cip ";
$DB->query($sql2);  //动态统计亲情类许愿
$res2=$DB->get_rows_array($sql2); //生成二维数组
$rows_count2=count($res2);  //统计二维数组的数量
$arraynum2=array(); //声明城市”亲情类“许愿总数数组
$arraycip2=array();  //声明”亲情类“城市名称数组
//解析数组
for($k=0;$k<$rows_count2;$k++){
 array_push($arraynum2,$res2[$k][num]); //输出城市的许愿数量
 array_push($arraycip2,$res2[$k][cip]);  //输出城市名称
}
/*************************************************************/
//创建画布
$graph = new PieGraph(320,246);  //创建画布
$graph->SetShadow(); //设置阴影
$graph->title->Set("统计分析全部区域的[ 亲情类 ] 许愿比率");  //设置标题名称
$graph->title->SetFont(FF_SIMSUN,FS_BOLD); //设置标题的字体加粗
$graph->legend->SetFont(FF_SIMSUN,FS_NORMAL); //设置饼形图文字的字体
$size=0.3;  //设置饼形图的半径
/***********************统计亲情许愿比率*************************/
$p= new PiePlot3D($arraynum2); //创建饼形图对象
$p->SetLegends($arraycip2);  //设置城市名称
$p->SetSize($size);  //设置饼形图的大小
$p->SetCenter(0.45,0.55); //设置饼形图的坐标位置
$p->value->SetFont(FF_FONT0); //设置字体
$p->title->SetFont(FF_SIMSUN,FS_BOLD); //设置标题字体加粗
/*************************************************************/
$graph->Add($p); //添加3D饼形图到图像中
$graph->Stroke(); //输出图像
?>

3,许愿墙列表,许愿墙字条高级搜索功能的实现
为了便于访客能更清晰地查看各种不同类别的许愿字条,本模块设计了爱墙列表和许愿字条高级搜索功能。其中,爱墙列表时在默认状态下检索全部的许愿字条,而高级搜索功能是按照访客设置的一定的查询条件来检索与之匹配的许愿字条。
设计爱墙列表及许愿字条高级搜索的表单元素如下:
<table width="1004" height="25" border="0" cellpadding="0" cellspacing="0">
 <form name="form" method="get" action=""> 
  <tr>
   <td align="center" bgcolor="#339933">请输入查询条件:
    <input type="text" name="content1" size="30" class="inputs"> 
    <select name="select">
    <option value="奥运会">奥运会</option>
    <option value="汶川">汶川</option>
    <option value="爱情">爱情</option>
    <option value="亲情">亲情</option>
    <option value="友情">友情</option>
    <option value="自己">自己</option>
    <option value="全部" selected="selected">全部</option>
    </select>
    <input type="submit" name="submit" value="检索许愿" class="btn_search">
     (支持多条件查询,如:爱墙号、许愿人、许愿内容等) 
   </td>
       </tr>
    </form>
</table>

4,许愿墙显示效果如图:
深入PHP许愿墙模块功能分析
PHP 相关文章推荐
利用discuz实现PHP大文件上传应用实例代码
Nov 14 PHP
Session保存到数据库的php类分享
Oct 24 PHP
ThinkPHP写第一个模块应用
Feb 20 PHP
关于php操作mysql执行数据库查询的一些常用操作汇总
Jun 24 PHP
PHP和JavaScrip分别获取关联数组的键值示例代码
Sep 16 PHP
php中用memcached实现页面防刷新功能
Aug 19 PHP
php可生成缩略图的文件上传类实例
Dec 17 PHP
用php来限制每个ip每天浏览页面数量的实现思路
Feb 24 PHP
隐藏Nginx或Apache以及PHP的版本号的方法
Jan 03 PHP
php操纵mysqli数据库的实现方法
Sep 18 PHP
php 实现简单的登录功能示例【基于thinkPHP框架】
Dec 02 PHP
分享8个Laravel模型时间戳使用技巧小结
Feb 12 PHP
解析PHP留言本模块主要功能的函数说明(代码可实现)
Jun 25 #PHP
深入PHP购物车模块功能分析(函数讲解,附源码)
Jun 25 #PHP
基于PHP+Ajax实现表单验证的详解
Jun 25 #PHP
PHP Class&amp;Object -- 解析PHP实现二叉树
Jun 25 #PHP
PHP Class&amp;Object -- PHP 自排序二叉树的深入解析
Jun 25 #PHP
通过PHP current函数获取未知字符键名数组第一个元素的值
Jun 24 #PHP
PHP多例模式介绍
Jun 24 #PHP
You might like
php下实现伪 url 的超简单方法[转]
2007/09/24 PHP
浅析linux下apache服务器的配置和管理
2013/08/10 PHP
详解PHP中的PDO类
2015/07/06 PHP
php实现的农历算法实例
2015/08/11 PHP
CI框架集成Smarty的方法分析
2016/05/17 PHP
Yii2针对指定url的生成及图片等的引入方法小结
2016/07/18 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
在js中使用&quot;with&quot;语句中跨frame的变量引用问题
2007/03/08 Javascript
JS链式调用的实现方法
2013/03/07 Javascript
input链接页面、打开新网页等等的具体实现
2013/12/30 Javascript
JQuery的ON()方法支持的所有事件罗列
2015/02/28 Javascript
基于jQuery+PHP+Mysql实现在线拍照和在线浏览照片
2015/09/06 Javascript
jQuery实现有动画淡出效果的二级折叠菜单代码
2015/10/17 Javascript
JavaScript小技巧整理篇(非常全)
2016/01/26 Javascript
浅谈JavaScript的内置对象和浏览器对象
2016/06/03 Javascript
Javascript中级语法快速入手
2016/07/30 Javascript
jQuery获取table下某一行某一列的值实现代码
2017/04/07 jQuery
Angular 4.x中表单Reactive Forms详解
2017/04/25 Javascript
bootstrap选项卡扩展功能详解
2017/06/14 Javascript
koa2使用ejs和nunjucks作为模板引擎的使用
2018/11/27 Javascript
解决vue axios跨域 Request Method: OPTIONS问题(预检请求)
2020/08/14 Javascript
[44:15]国士无双DOTA2 6.82版本详解(上)
2014/09/28 DOTA
python查询mysql中文乱码问题
2014/11/09 Python
状态机的概念和在Python下使用状态机的教程
2015/04/11 Python
详解使用Python处理文件目录的相关方法
2015/10/16 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
python实现网站用户名密码自动登录功能
2019/08/09 Python
python os模块在系统管理中的应用
2020/06/22 Python
Java提供了哪些企业应用编程接口
2015/02/13 面试题
学校联谊活动方案
2014/02/15 职场文书
小学生学习雷锋倡议书
2014/05/15 职场文书
求职简历自我评价怎么写
2015/03/10 职场文书
纪律委员竞选稿
2015/11/19 职场文书
浅谈怎么给Python添加类型标注
2021/06/08 Python
浅谈Java父子类加载顺序
2021/08/04 Java/Android
Sentry的安装、配置、使用教程(Sentry日志手机系统)
2022/07/23 Python