抽时间对照着案例撸了一遍,学到了蛮多东西,也有很多疑问,其中有个疑问仍是没有撸明白
graph.width = graph.width; //所谓的巧妙用法?
好了废话不多说,贴出源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript Loan Calcualtor</title>
<style>
.output {
font-weight: bold
}
#payment {
text-decoration: underline
}
#graph {
border: solid black 1px
}
th, td {
vertical-align: top
}
</style>
<script>
"user strict"; //如果浏览器支持的话,则开启ECMAScript 5的严格模式
// 查找文档中用于输入输出的元素
function $(id) {
return document.getElementById(id);
}
function calculate() {
//假设所有的输入都是合法的, 将从input元素中获取输入数据
//将百分比格式转换为小数格式, 并从年利率转换为月利率
//将年度赔付转换为月度赔付
var amount = $("amount"),
apr = $("apr"),
years = $("years"),
zipcode = $("zipcode"),
payments = $("payment"),
total = $("total"),
totalInterest = $("totalInterest"),
principal = parseFloat(amount.value),
interest = parseFloat(apr.value) / 100 / 12,
payment = parseFloat(years.value) * 12;
//现在计算月度赔付的数据
var x = Math.pow(1 + interest, payment),
monthly = (principal * x * interest) / (x - 1);
if (isFinite(monthly)) {
//四舍五入到小数点后两位数字
payments.innerHTML = monthly.toFixed(2);
total.innerHTML = (monthly * payment).toFixed(2);
totalInterest.innerHTML = ((monthly * payment) - principal).toFixed(2);
//将用户输入的数据保存下来,这样在下次访问的时候也能取到数据
save(amount.value, apr.value, years.value, zipcode.value);
try { //捕获这段代码抛出的所有异常
getLenders(amount.value, apr.value, years.value, zipcode.value);
}
catch (e) {/* 忽略这些异常 */
}
//最后用图标展示贷款余额、利息和资产收益
chart(principal, interest, monthly, payment);
} else {
payment.innerHTML = "";
total.innerHTML = "";
totalInterest.innerHTML = "";
chart();
}
}
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.lan_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) {
if (window.XMLHttpRequest) return;
var ad = document.getElementById("lenders");
if (!ad) return;
var url = "getLenders.php" +
"?amt=" + encodeURIComponent(amount) +
"&apr=" + encodeURIComponent(apr) +
"&yrs=" + encodeURIComponent(years) +
"&zip=" + encodeURIComponent(zipcode);
var req = new XMLHttpRequest();
req.open("GET", url);
req.send(null); //不带任何正文发送这个请求
req.onreadystatechange = function () {
if (req.readyState == 4 && req.status == 200) {
var respones = req.responseText;
var lenders = JSON.pares(response); //将其解析为js数组
var list = "";
for (var i = 0; i < lenders.length; i++) {
list += "<li><a href=' " + lenders[i].url + " '>" + lenders[i].name + "</a>";
}
ad.innerHTML = "<ul>" + list + "</ul>"
}
}
}
function chart(principal, interest, monthly, payment) {
var graph = document.getElementById("graph");
//如果不传入参数,或者浏览器不支持画布,则直接返回
if (arguments.length == 0 || !graph.getContext) return;
//graph.width = graph.width; //所谓的巧妙用法?
//获得画布元素的"context"对象,这个对象定义了一组绘画API
var g = graph.getContext("2d");
var width = graph.width,
height = graph.height;
//将付款数字和美元数据转换为像素
function paymentToX(n) {
return n * width / payment;
}
function amountToY(a) {
return height - (a * height / (monthly * payment * 1.05));
}
//画线
// 付款数据是一条从(0,0)到()
g.moveTo(paymentToX(0), amountToY(0)); //起点
g.lineTo(paymentToX(payment), amountToY(monthly * payment));
g.lineTo(paymentToX(payment), amountToY(0));
g.closePath();
g.fillStyle = "#f88"; //亮红色
g.fill();
g.font = "bold 12px sans-serif"; //自定义一种字体
g.fillText("Total Interest Payments", 20, 20); //将文字绘制到图例中
//很多资产数据并不是线性的,很难将其反映至图表中
var equity = 0;
g.beginPath();
g.moveTo(paymentToX(0), amountToY(0));
for (var p = 1; p <= payment; p++) {
//计算出每一笔赔付的利息
var thisMonthsInterest = (principal - equity) * interest;
equity += (monthly - thisMonthsInterest);
g.lineTo(paymentToX(p), amountToY(equity));
}
g.lineTo(paymentToX(payment), amountToY(0));
g.closePath();
g.fillStyle = "green";
g.fill();
g.fillText("Total Equity", 20, 35);
//再次循环, 余额数据显示未黑色粗线条
var bal = principal;
g.beginPath();
g.moveTo(paymentToX(0), amountToY(bal));
for (var p = 1; p <= payment; p++) {
var thisMonthsInterest = bal * interest;
bal -= (monthly - thisMonthsInterest);
g.lineTo(paymentToX(p), amountToY(bal));
}
g.lineWidth = 3;
g.stroke();
g.fillStyle = "black";
g.fillText("Loan Balance", 20, 50);
//将年度数据在X轴做标记
g.textAlign = "center";
var y = amountToY(0);
for (var year = 1; year * 12 <= payment; year++) {
var x = paymentToX(year * 12);
g.fillRect(x - 0.5, y - 3, 1, 3); //开始绘制标记
if (year == 1) g.fillText("Year", x, y - 5);
if (year % 5 == 0 && year * 12 !== payment) {
g.fillText(String(year), x, y - 5);
}
}
//将赔付数额标记在右边界
g.textAlign = "right";
g.textBaseline = "middle"; //文字垂直居中
var ticks = [monthly * payment, principal];
var rightEdge = paymentToX(payment);
for (var i = 0; i < ticks.length; i++) {
var y = amountToY(ticks[i]);
g.fillRect(rightEdge - 3, y - 0.5, 3, 1);
g.fillText(String(ticks[i].toFixed(0)),
rightEdge - 5, y);
}
}
</script>
</head>
<body>
<table>
<tr>
<th>Enter Loan Data:</th>
<td></td>
<th>Loan Balance, Cumulative Equity, and Interest Payments</th>
</tr>
<tr>
<td>Amount of the loan ($):</td>
<td><input id="amount" onchange="calculate()"></td>
<td rowspan=8>
<canvas id="graph" width="400" height="250"></canvas>
</td>
</tr>
<tr>
<td>Annual interest (%):</td>
<td><input id="apr" onchange="calculate()"></td>
</tr>
<tr>
<td>Repayment period (years):</td>
<td><input id="years" onchanges="calculate"></td>
</tr>
<tr>
<td>Zipcode (to find lenders):</td>
<td><input id="zipcode" onchange="calculate()"></td>
</tr>
<tr>
<th>Approximate Payments:</th>
<td>
<button onclick="calculate()">Calculate</button>
</td>
</tr>
<tr>
<td>Monthly payment:</td>
<td>$<span class="output" id="payment"></span></td>
</tr>
<tr>
<td>Total payment:</td>
<td>$<span class="output" id="total"></span></td>
</tr>
<tr>
<td>Total interest:</td>
<td>$<span class="output" id="totalInterest"></span></td>
</tr>
<tr>
<th>Sponsors:</th>
<td colspan=2>Apply for your loan with one of these fine lenders:
<div id="lenders"></div>
</td>
</tr>
</table>
</body>
</html>
贴上最终效果图:
扔在起点摸索中,欢迎大佬解答疑惑。