基于JavaScript实现的贷款计算器
本文实现的技术:
- 如何在文档中查找元素
- 如何通过表单Input元素来获取用户输入的数据
- 如何通过元素来设置HTML内容
- 如何将数据存储在浏览器中
- 如何使用脚本发起HTTP请求
- 如何利用元素绘图
先看成果

HTML部分
<table id="myTable">
<tr>
<th>输入贷款数据</th>
<td></td>
<th>贷款余额、累计权益和利息支付</th>
</tr>
<tr>
<td>贷款金额 ($):</td>
<td><input id="amount" onchange="calculate()"/></td>
<td rowspan=8>
<canvas id='graph' width=400 height=250></canvas>
</td>
</tr>
<tr>
<td>
年利息(%):
</td>
<td><input id='apr' onchange="calculate()"/></td>
</tr>
<tr>
<td>
还款期(年):
</td>
<td><input id='years' onchange="calculate()"/></td>
</tr>
<tr>
<td>
邮政编码(查找贷方):
</td>
<td><input id='zipcode' onchange="calculate()"/></td>
</tr>
<tr>
<td>
接近付款:
</td>
<td><button onclick="calculate()">计算</button></td>
</tr>
<tr>
<td>
每月付款:
</td>
<td>$<span class="output" id="payment"></span></td>
</tr>
<tr>
<td>
付款总额:
</td>
<td>$<span class="output" id="total"></span></td>
</tr>
<tr>
<td>
总利息:
</td>
<td>$<span class="output" id="totalinterest"></span></td>
</tr>
<tr>
<th>
赞助商:</th><td colspan=2>
向这些优秀的贷款人申请贷款:
<div id="lenders"></div>
</td>
</tr>
</table>
CSS部分
#myTable{
margin: auto; //居中
}
.output{
font-weight: bolder; //计算结果定义为粗体
}
#payment{
text-decoration: underline; //定义id为payment的元素样式
}
#graph{
border: solid black 1px; //图表有一个1像素的边框
}
th td{
vertical-align: top; //表格单元与其对齐方式为顶端对齐
}
JS部分
function calculate(){
// 贷款金额
var amount = document.getElementById('amount');
// 年利息
var apr = document.getElementById('apr');
// 还款期
var years = document.getElementById('years');
//贷款方
var zipcode = document.getElementById('zipcode');
// 每月支付
var payment = document.getElementById('payment');
// 总支付
var total = document.getElementById('total');
// 总利息
var totalinterest = document.getElementById('totalinterest');
// amount 贷款总额
var principle = parseFloat(amount.value);
// apr 年利率
var interest = parseFloat(apr.value) /100 /12;
// 偿还周期 月份
var payments = parseFloat(years.value) * 12;
// pow 求次幂
var x = Math.pow(1 + interest, payments);
// monthly 每月还款金额
var monthly = (principle * x * interest) / (x-1);
//如果没有超过数字范围,且用户输入也正确
if(isFinite(monthly)){
payment.innerHTML = monthly.toFixed(2);
total.innerHTML = (monthly * payments).toFixed(2);
totalinterest.innerHTML = (monthly * payments - principle).toFixed(2);
// 保存数据到本地
save(amount.value, apr.value, years.value, zipcode.value);
// 借贷人,忽略网络错误
try{
getLenders(amount.value, apr.value, years.value, zipcode.value);
}
catch (e) {
//忽略异常
}
// 画图
chart(principle, interest, monthly, payments);
}else{
//计算结果不是数字或者无穷大,意味着输入数据是非法或不完整的
//清空数据
payment.innerHTML = "";
total.innerHTML = "";
totalinterest.innerHTML = "";
chart();
}
}
//将用户输入保存至localSorage对象的属性中
function save(amount, apr, years, zipcode){
if(window.localStorage){//只有支持的浏览器才能运行这个代码
localStorage.loan_amount = amount;
localStorage.loan_apr = apr;
localStorage.loan_years = years;
localStorage.loan_zipcode = zipcode;
}
}
//文档首次加载的时,将会尝试还原输入字段
window.onload = function(){
//如果浏览器支持本地存储并且上次保存的值也是存在的
if(window.localStorage && localStorage.loan_amount){
document.getElementById('amount').value = localStorage.loan_amount;
document.getElementById('apr').value = localStorage.loan_apr;
document.getElementById('years').value = localStorage.loan_years;
document.getElementById('zipcode').value = localStorage.loan_zipcode;
}
}
//将用户的输入发送至服务器上
function getLenders(amount,apr,years,zipcode) {
//如果浏览器不支持XMLHttpRequest对象,则退出
if(!window.XMLHttpRequest) return;
//找到要显示放贷人列表的元素
var ad =document.getElementById("lenders");
if(!ad) return; //如果为空则退出
//将用户的输入数据进行URL编码,并将查询参数附加在URL里
var url ="getLenders.php" + //处理数据的URL地址
"?amt="+encodeURIComponent(amount)+ //使用查询串中的数据
"&apr="+encodeURIComponent(apr) +
"&yrs="+encodeURIComponent(years) +
"&zip="+encodeURIComponent(zipcode);
//通过XMLHttpRequest对象提取返回数据
var req=new XMLHttpRequest() //发起一个新的请求
req.open("GET",url); //通过URL发起一个HTTP GRT请求
req.send(null) //不带任何正文发送这个请求
//返回数据之前,注册一个事件处理函数,这个处理函数
//绘制服务器的响应返回至客户端的时候调用
//这种异步编程模型在客户端JS中是非常常见的
req.onreadystatechange=function () {
if(req.readyState == 4 && req.status ==200){
//如果代码运行到这里,说明得到了以后合法且完整的HTTP响应
var response =req.responseText; //HTTP响应是以字符串的形式呈现的
var lenders =JSON.parse(response) //将其解析为JS数组
//将数组中的贷款人对象转换为HTML字符串形式
var list =""
for (let i=0;i<lenders.length;i++ ){
list +="<li><a href ='"+lenders[i].url+"'>"+
lenders[i].name + "</a>";
}
//将数据在HTML元素中呈现出来
ad.innerHTML ="<ul>" + list +"</ul>";
}
}
}
//在HTML<canvas>元素中用图表展示贷款余额、利息和资产收益
//如果不传参的话则清空之前图表数据
function chart(principle, interest, monthly, payments){
var graph = document.getElementById('graph'); //得到canvas标签
graph.width = graph.width; //巧妙的清除并重置画布
//如果不传参。或者浏览器不支持画布,则直接返回
if(arguments.length == 0||!graph.getContext) return;
//获取画布元素的“context”对象,这个对象定义了一组绘画API
var g = graph.getContext('2d'); //所有的绘画操作将基于这个对象
var width = graph.width;
var height = graph.height; //获得画布大小
// 将付款数字和美元数据转换为像素
function paymentToX(n){
return n * width / payments;
}
function amountToY(a){
return height - a * height / (monthly * payments * 1.05);
}
//付款数据是一条从(0,0)到(payments,monthly*payments)
g.moveTo(paymentToX(0), amountToY(0)); //从左下开始
g.lineTo(paymentToX(payments), amountToY(monthly * payments));//至右上
g.lineTo(paymentToX(payments), amountToY(0)); //至右下
g.closePath(); //将结尾链接值开头
g.fillStyle = '#f88'; //亮红色
g.fill(); //填充矩形
g.font = "bold 12px sans-serif"; //定义字体
//g.fillStyle = "yellow";
g.fillText("利息支付总额", 20, 20); //将文字绘制到图列中
// 很多资产数据不是线性的,很难将其反印到图表中
var equity = 0;
g.beginPath(); //开始绘制图形
g.moveTo(paymentToX(0), amountToY(0)); //左下开始
for( var p = 1; p<=payments; p++){ //计算出每一笔赔付的利息
var thisMonthsInterest = (principle - equity) * interest;
equity += (monthly - thisMonthsInterest); //得到资产额
g.lineTo(paymentToX(p), amountToY(equity)); //将数据绘制到画布上
}
g.lineTo(paymentToX(payments), amountToY(0)); //将数据绘制到X轴
g.closePath(); //将线条结尾连接至线条开头
g.fillStyle = 'green'; //绿色
g.fill(); //曲线下面均匀填充
g.fillText('总权益', 20, 35); //文本设置成绿色
//画余额
var bal = principle;
g.beginPath();
g.moveTo(paymentToX(0), amountToY(bal));
for(var p=1; p<payments;p++){
var thisMonthsInterest = bal*interest;
bal-= (monthly - thisMonthsInterest); //得到资产额
g.lineTo(paymentToX(p), amountToY(bal)); //将直线连接至某点
}
g.lineWidth = 3; //将直线宽度加粗
g.fillStyle='black'; //使用黑色字体
g.stroke(); //绘制余额的曲线
g.fillText("贷款余额", 20, 50); //图例文字
//将年度数据在X轴做标记
g.textAlign = 'center'; //文字居中对齐
var y = amountToY(0); //Y坐标设为0
for(var year=1; year*12<=payments;year++){ //遍历每年
var x = paymentToX(year*12); //计算标记位置
g.fillRect(x-0.5, y-3, 1, 3); //开始绘制标记
if(year ==1){ //在坐标轴做标记
g.fillText("0",x,y-5);
}
if(year % 5==0 && year*12 !== payments){ //每五年的数据
g.fillText(String(year),x,y-5);
}
}
//将赔付数额标记在右边界
g.textAlign = "right"; //文字右对齐
g.textBaseline = "middle"; //文字垂直居中
g.fillStyle='black';
var ticks = [monthly*payments, principle]; //将用到的两个点
var rightEdge = paymentToX(payments); //设置X坐标
for(let i=0;i<ticks.length;i++){ //对每两个点循环
var y = amountToY(ticks[i]); //计算每个标记的Y坐标
g.fillRect(rightEdge -3, y-0.5,3,1); //绘制标记
g.fillText(String(ticks[i].toFixed(0)), rightEdge-5, y); //绘制文本
}
}
本文介绍了如何使用JavaScript来实现一个贷款计算器,涵盖了查找HTML元素、获取用户输入、设置HTML内容、存储数据、发起HTTP请求以及利用元素绘图等技术。

2509

被折叠的 条评论
为什么被折叠?



