JavaScript权威指南----一个JavaScript贷款计算器
废话不多说上例子代码:
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>JavaScript Loan Calculator</title> 7 <style> 8 .output{font-weight: bold;} 9 #payment{text-decoration: underline;} 10 #graph{border: 1px solid black;} 11 th, td{vertical-align: top;} 12 13 </style> 14 </head> 15 16 <body> 17 <table> 18 <tr> 19 <th>Enter Loan Data:</th> 20 <td></td> 21 <th>Loan Balance,Cumulative Equity,and Interest Payments</th> 22 </tr> 23 <tr> 24 <td>Amount of the loan($):</td> 25 <td><input id="amount" οnchange="calculate();"/></td> 26 <!--数量--> 27 <td rowspan="8"><canvas id="graph" width="400" height="250"></canvas></td> 28 <!--图表--> 29 </tr> 30 <tr> 31 <td>Annual interest(%):</td> 32 <td><input id="apr" οnchange="calculate();" /></td> 33 <!--年百分利率--> 34 </tr> 35 <tr> 36 <td>Repayment period (years):</td> 37 <td><input id="years" οnchange="calculate();" /></td> 38 </tr> 39 <tr> 40 <td>Zipcode (to find lenders):</td> 41 <td><input id="zipcode" οnchange="calculate();" /></td> 42 <!--邮政编码--> 43 </tr> 44 <tr> 45 <td>Approximate Payments:</td> 46 <td><button id="years" onclick="calculate();">Calculate</button></td> 47 <!--计算--> 48 </tr> 49 <tr> 50 <td>Monthly payment:</td> 51 <td>$<span class="output" id="payment"></span></td> 52 <!--付款--> 53 </tr> 54 <tr> 55 <td>Total interest:</td> 56 <td>$<span class="output" id="total"></span></td> 57 <!--全部的--> 58 </tr> 59 <tr> 60 <td>Total payment:</td> 61 <td>$<span class="output" id="totalinterest"></span></td> 62 <!--总利息--> 63 </tr> 64 <tr> 65 <th>Spinsors:</th> 66 <td colspan="2"> 67 Apply for your loan with one of these fine lenders: 68 <div id="lenders"></div> 69 <!--贷款人--> 70 </td> 71 </tr> 72 </table> 73 <script> 74 //"use strict"; 75 function calculate(){ 76 //查找文档中用于输入输出的元素 77 var amount = document.getElementById("amount"); 78 var apr = document.getElementById("apr"); 79 var years = document.getElementById("years"); 80 var zipcode = document.getElementById("zipcode"); 81 var payment = document.getElementById("payment"); 82 var total = document.getElementById("total"); 83 var totalinterest = document.getElementById("totalinterest"); 84 85 //假如所有的输入都是合法的,将从input中获取输入数据 86 //将百分比格式转换成小数格式,并从年利率转化成月利率 87 //将年度赔付装换成月度赔付 88 var principal = parseFloat(amount.value); 89 var interest = parseFloat(apr.value)/100/12; 90 var payments = parseFloat(years.value)*12; 91 92 //现在计算月度赔付的数据 93 var x =Math.pow(1+interest,payments);//Math.pow()进行幂次运算 94 var monthly = (principal*x*interest)/(x-1); 95 96 //如果结果没有超过js能表示的数字范围,且用户的输入也正确 97 //这里所展示的结果就是合法的 98 if(isFinite(monthly)){ 99 //将数字填充到输出字段的位置,四舍五入到小数点后两位数字 100 payment.innerHTML = monthly.toFixed(2); 101 total.innerHTML = ((monthly*payments)-principal).toFixed(2); 102 totalinterest.innerHTML=((monthly*payments)-principal).toFixed(2); 103 104 //将用户输入的数据保存下来,这样下次访问时候也能取到数据 105 save(amount.value,apr.value,years.value,zipcode.value); 106 107 //找到并展示放贷人,但忽略网络错误 108 try{ 109 //捕获这段代码抛出的所有异常 110 getLenders(amount.value,apr.value,years.value,zipcode.value); 111 } 112 //忽略这些异常 113 catch(e){} 114 115 //最后,用图表展示贷款余额,利息和资产收益 116 chart(principal,interest,monthly,payments); 117 }else{ 118 payment.innerHTML=""; 119 total.innerHTML=""; 120 totalinterest.innerHTML=""; 121 chart(); 122 } 123 } 124 125 function save(amount,apr,years,zipcode){ 126 if(window.localStorage){//只有在浏览器支持的时候才支持这里的代码 127 localStorage.loan_amount = amount; 128 localStorage.loan_apr = apr; 129 localStorage.loan_years = years; 130 localStorage.loan_zipcode = zipcode; 131 } 132 } 133 134 //文档首次加载的时候,将会尝试还原输入字段 135 window.οnlοad=function(){ 136 //如果浏览器支持本地存储并且上次保存的值是存在的 137 if(window.localStorage && localStorage.loan_amount){ 138 document.getElementById("amount").value = localStorage.loan_amount; 139 document.getElementById("apr").value = localStorage.loan_apr; 140 document.getElementById("years").value = localStorage.loan_years; 141 document.getElementById("zipcode").value = localStorage.loan_zipcode; 142 } 143 } 144 145 //将用户的输入发送到服务器端脚本返回一个本地放贷人的连接列表,在这个例子中并没有是现在这种查找放贷人的服务 146 //但如果该服务存在,该函数会使用它 147 function getLenders(amount,apr,years,zipcode){ 148 //如果浏览器不支持XMLHttpRequest对象,则退出 149 if (!window.XMLHttpRequest)return; 150 151 //找到要显示放贷人列表的元素 152 var ad=document.getElementById("lenders"); 153 if(!ad)return;//如果返回为空则退出 154 155 //将用户的输入数据进行url编码,并作为查询参数附加在URL里 156 var url = "getLenders.php"+ 157 "?amt" + encodeURLComponent(amount)+ 158 "?apr" + encodeURLComponent(apr)+ 159 "?yrs" + encodeURLComponent(years)+ 160 "?zip" + encodeURLComponent(zipcode); 161 162 //用XMLHttpRequest对象来提取返回数据 163 var req = new XMLHttpRequest();//发送一个新的请求 164 req.open("GET",url);//通过url发起一个http get请求 165 req.send(null);//不带任何正文发送这个请求 166 167 //在返回数据之前,注册一个事件处理函数,这个处理函数将会在服务器的的响应返回至客户端的时候调用 168 //这个异步边城模型在客户端js中是非常常见的 169 req.onreadystatechange = function(){ 170 if(req.readyState == 4 && req.status == 200){ 171 //如果代码运行到这里,说明我们得到了一个合法且完整的http响应 172 var response = req.responseText;//http响应是以字符串的形式呈现的 173 var lenders = JSON.parse(response);//将其解析为js数组 174 175 //将数组中的放贷人对象转换成HTML字符串的形式 176 var list=""; 177 for(var i=0;i<lenders.length;i++){ 178 list += "<li><a href='"+ lenders[i].url +"'>"+lenders[i].name+"</a></li>" 179 } 180 181 //将数据在HTML中呈现出来 182 ad.innerHTML = "<ul>"+list+"</ul>"; 183 } 184 } 185 186 } 187 188 //在HTML<canvas>元素中用图表展示月度贷款余额,利息和资产情况 189 //如果不传参就清空之前的图表 190 function chart(principal,interest,monthly,payments){ 191 var graph = document.getElementById("graph"); 192 graph.width = graph.width;//用一种巧妙的手法清除并重置画布 193 194 //如果不传入参数,或者浏览器不支持画布,则直接返回。 195 if(arguments.length == 0 || !graph.getContext)return; 196 197 //获得画布元素『context』对象,这个对象定义了一组绘画API 198 var g = graph.getContext("2d"); 199 var width = graph.width,height = graph.height; 200 201 //这里的函数的作用是将付款数字和美元数字转换成像素 202 function paymentToX(n){ 203 return n*width/payments; 204 } 205 function amountToY(a){ 206 return height - (a*height/(monthly*payments*1.05)); 207 } 208 209 //付款数据是一条从(0,0)到(payments,monthly*payments)的直线 210 g.moveTo(paymentToX(0),amountToY(0)); 211 g.lineTo(paymentToX(payments),amountToY(monthly*payments)); 212 g.lineTo(paymentToX(payments),amountToY(0)); 213 g.closePath(); 214 g.fillStyle = "#f88"; 215 g.fill(); 216 g.font = "bold 12px sans-serif"; 217 g.fillText("Total Interest Payments",20,20); 218 219 //很多资产数据并不是线性的,很难将其反映到图标中 220 var equity = 0; 221 g.beginPath(); 222 g.moveTo(paymentToX(0),amountToY(0)); 223 for(var p=1;p<=payments;p++){ 224 //计算出每一笔赔付的利息 225 var thisMonthsINterest = (principal - equity)*interest; 226 equity += (monthly -thisMonthsInterest); 227 g.lineTo(paymentToX(p),amountToY(equity)); 228 } 229 g.lineTo(paymentToX(payments),amountToY(0)); 230 g.closePath(); 231 g.fillStyle = "green"; 232 g.fill(); 233 g.fillText("Total Equity",20,35); 234 235 //再次循环,余额数据显示为黑色粗线条 236 var bal = principal; 237 g.beginPath(); 238 g.moveTo(paymentToX(0),amountToY(bal)); 239 for(var p=1;p<=payments;p++){ 240 var thisMonthsInterest = bal*interest; 241 bal-=(monthly - thisMonthsInterest); 242 g.lineTo(paymentToX(p),amountToY(bal)); 243 } 244 245 g.lineWidth = 3; 246 g.stroke(); 247 g.fillStyle ="black"; 248 g.fillText("Loan Balance",20,50); 249 250 //将年度数据在X轴做标记 251 g.textAlign = "center"; 252 var y = amountToY(0); 253 for(var year = 1;year*12<=payments;year++){ 254 var x=paymentToX(year*12); 255 g.fillRect(x-0.5,y-3,1,3); 256 if(year == 1) g.fillText("Year",x,y-5); 257 if(year %5 ==0 && year*12 !== payments) 258 g.fillText(String(year),x,y-5); 259 } 260 261 //将赔付数额标记在右边界 262 g.textAlign = "right"; 263 g.textBaseline ="middle"; 264 var ticks = [monthly * payments,principal]; 265 var rightEdge = paymentToX(payments); 266 for(var i=0;i<ticks.length;i++){ 267 var y = amountToY(ticks[i]); 268 g.fillRect(rightEdge-3,y-0.5,3,1); 269 g.fillText(String(ticks[i].toFixed(0)),rightEdge-5,y); 270 } 271 } 272 </script> 273 </body> 274 275 </html>
这边例子有个我感觉错误的地方:
1 <tr> 2 <td>Approximate Payments:</td> 3 <td><button id="years" onchange="calculate();">Calculate</button></td> 4 <!--计算--> 5 </tr>
这里的onchange是无法触发这个计算函数,需要改成onclick函数;
学习如逆水行舟,不进则退。