JavaScript 学习第一章
阿明
撰写于 2024年 05月 02 日

javascript学习第一章

1.1 类型、对象,简单使用:

  • 定义对象

    var book = { topic: "JavaScript", fat: true };
  • 读取对象

    book.topic book["fat]
  • 赋值

    book.author = "Flanagan" book.contents = {};
  • 定义数组

     var primes = [2,3,5,7]
  • 读取数组

    primes[0]
  • 数组中元素替换

    primes[4] = 9;
  • 定义多级数组

    var points = [ {x:0,y:0}, {x:1,y:1} ];
  • 对象中有数组

    var data = { trial1:[[1,2],[3,4]], trial1:[[2,3],[4,5]] };
  • 读取

    data.trial1[0][1]
  • 定义函数

     function plus1(x){ return x+1; }
  • 调用函数

    plus1(y)
  • 定义构造函数初始化 Point 对象

    function Point(x,y){ this.x = x; this.y = y; }
  • 使用 new 创建实例

    var p = new Point(1,1);
  • 使用构造函数的 prototype 对象赋值给 Point 对象定义方法

    Point.prototype.r = function(){ return Math.sqrt(this.x * this.x + this.y * this.y);};
  • 调用方法

    p.r()

1.2 写个贷款计算器

1.2.1 前端代码

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript Loan Calculator</title>
    <style>
      .output {
        font-weight: bold;
        #payment {
          text-decoration: underline;
        }
        #graph {
          border: solid black 1px;
        }
        th,
        td {
          vertical-align: top;
        }
      }
    </style>
  </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" onchange="calculate();" /></td>
      </tr>

      <tr>
        <td>Zipcode(to fnd 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 fne lenders:
          <div id="lenders"></div>
        </td>
      </tr>
    </table>
    <script>
      'use script'; //如果浏览器支持开启ECMAScript 5严格模式
      /**这里的脚本定义了caculate()函数,在HTML代码中绑定事件处理程序时会调用它丰这个函数从<input>元素中读取数据,计算贷款赔付信息,并将结果显示在<span>元素中*同样,这里还保存了用户数据、展示了放贷人链接并绘制出了图表*/
      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');
        //假设所有的输入都是合法的,将从input元素中获取输入数据
        //将百分比格式转换为小数格式,并从年利率转换为月利率
        //将年度赔付转换为月度赔付
        var principal = parseFloat(amount.value);
        var interest = parseFloat(apr.value) / 100 / 12;
        var payments = parseFloat(years.value) * 12;
        //现在计算月度赔付的数据
        var x = Math.pow(1 + interest, payments); // Math.pow()进行幂次运算
        var monthly = (principal * x * interest) / (x - 1);
        //如果结果没有超过JavaScript能表示的数字范围,且用户的输入也正确
        //这里所展示的结果就是合法的
        if (isFinite(monthly)) {
          //将数据填充至输出字段的位置,四舍五入到小数点后两位数字
          payment.innerHTML = monthly.toFixed(2);
          total.innerHTML = (monthly * payments).toFixed(2);
          totalinterest.innerHTML = (monthly * payments - principal).toFixed(2);
          //将用户的输入数据保存下来,这样在下次访问时也能取到数据
          save(amount.value, apr.value, years.value, zipcode.value);
          //找到并展示本地放贷人,但忽略网络错误
          try {
            // 捕获这段代码抛出的所有异常
            getLenders(amount.value, apr.value, years.value, zipcode.value);
          } catch (e) {
            /*忽略这些异常 */
            console.log(e);
          }
          //最后,用图表展示贷款余额、利息和资产收益
          chart(principal, interest, monthly, payments);
        } else {
          //计算结果不是数字或者是无穷大,意味着输入数据是非法或不完整的
          //清空之前的输出数据
          payment.innerHTML = ''; // 清空元素的文本内容
          total.innerHTML = '';
          totalinterest.innerHTML = '';
          chart(); //不传参数的话就是清除图表
        }
      }
      //将用户的输入保存至1ocalstorage对象的属性中
      //这些属性在再次访间时还会继续保持在原位置
      //如果你在浏览器中按照fle://URL的方式直接打开本地文件,
      //则无法在某些浏览器中使用存储功能(比如FireFox)
      //而通过HTTP打开文件是可行的
      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 =
          'http://127.0.0.1:8080/getlenders.php' + //处理数据的URL地址
          '?amt=' +
          encodeURIComponent(amount) + // 使用查询串中的数据
          '&apr=' +
          encodeURIComponent(apr) +
          '&yrs=' +
          encodeURIComponent(years) +
          '&zip=' +
          encodeURIComponent(zipcode);

        //通过XMLHttpRequest对象来提取返回数据
        var xhttp = new XMLHttpRequest(); //发起一个新的请求
        xhttp.open('GET', url); // 通过URL发起一个HTTP GET请求
        xhttp.send(null); //不带任何正文发送这个请求

        //在返回数据之前,注册了一个事件处理函数,这个处理的数
        //将会在服务器的响应返回至客户端的时候调用
        //这种异步编程模型在客户端]avascript中是非常常见的
        xhttp.onreadystatechange = function () {
          if (xhttp.readyState == 4 && xhttp.status == 200) {
            //如果代码运行到这里,说明我们得到了一个合法且完整的HTTP响应
            var response = xhttp.responseText; // HTTP响应是以字符串的形式呈现的
            var lenders = JSON.parse(response); //将其解析为]S数组
            //将数组中的放贷人对象转换为HTML字符串形式
            var list = '';
            for (var 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(principal, 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,
          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.fillText('Total Interest Payments', 20, 20); //将文字绘制到图例中
        //很多资产数据并不是线性的,很难将其反映至图表中
        var equity = 0;
        g.beginPath(); //开始绘制新图形

        g.moveTo(paymentToX(0), amountToY(0)); // 从左下方开始
        for (var p = 1; p <= payments; p++) {
          //计算出每一笔赔付的利息
          var thisMonthsInterest = (principal - 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('Total Equity', 20, 35); //文本颜色设置为绿色

        //再次循环,余额数据显示为黑色粗线条
        var bal = principal;
        g.beginPath();
        g.moveTo(paymentToX(0), amountToY(bal));
        for (varp = 1; p <= payments; 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); // 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('Year', x, y - 5); //在坐标轴做标记
          if (year % 5 == 0 && year * 12 !== payments)
            //每5年的数据
            g.fillText(string(year), x, y - 5);
        }

        //将赔付数额标记在右边界
        g.textAlign = 'right'; //文字右对齐
        g.textBaseline = 'middle'; //文字垂直居中
        var ticks = [monthly * payments, principal]; //我们将要用到的两个点
        var rightEdge = paymentToX(payments); // 设置X坐标
        for (var 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
          );
        }
      }
    </script>
  </body>
</html>

1.2.2 后端代码

1.2.2.1 后端控制层

package xm.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author heliming
 * @version 1.0
 * @date 2024/4/30-19:29
 * @description TODO
 */
@RestController
public class HelloController {

  //http://getlenders.php/?amt=100&apr=2&yrs=20&zip=23
  //  lenders[i].url +
  //                "'>" +
  //                lenders[i].name +

  @GetMapping("getlenders.php")
  public List<Map<String, String>> hello(Integer amt, Integer apr, Integer yrs,  Integer zip) {
    List<Map<String, String>> result = new ArrayList<>();
    Map<String, String> obj1 = new HashMap<>();
    obj1.put("url", "https://www.baidu.com");
    obj1.put("name", "百度");
    result.add(obj1);
    Map<String, String> obj2 = new HashMap<>();
    obj2.put("url", "https://www.taobao.com");
    obj2.put("name", "淘宝");
    result.add(obj2);
    System.out.println(result);
    return result;
  }
}

1.2.2.1 后端解决跨域

package xm.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
        .allowedOrigins("*") // 允许的前端域名或地址
        .allowedMethods("GET", "POST") // 允许的请求方法
        .allowedHeaders("*") // 允许的请求头
        .allowCredentials(true) // 允许携带凭证(如Cookie)
        .maxAge(3600); // 缓存预检请求的时间,单位秒
  }
}

1.2.3 图片

JavaScript 学习第一章

javascript学习第一章

1.1 类型、对象,简单使用:

  • 定义对象

    var book = { topic: "JavaScript", fat: true };
  • 读取对象

    book.topic book["fat]
  • 赋值

    book.author = "Flanagan" book.contents = {};
  • 定义数组

     var primes = [2,3,5,7]
  • 读取数组

    primes[0]
  • 数组中元素替换

    primes[4] = 9;
  • 定义多级数组

    var points = [ {x:0,y:0}, {x:1,y:1} ];
  • 对象中有数组

    var data = { trial1:[[1,2],[3,4]], trial1:[[2,3],[4,5]] };
  • 读取

    data.trial1[0][1]
  • 定义函数

     function plus1(x){ return x+1; }
  • 调用函数

    plus1(y)
  • 定义构造函数初始化 Point 对象

    function Point(x,y){ this.x = x; this.y = y; }
  • 使用 new 创建实例

    var p = new Point(1,1);
  • 使用构造函数的 prototype 对象赋值给 Point 对象定义方法

    Point.prototype.r = function(){ return Math.sqrt(this.x * this.x + this.y * this.y);};
  • 调用方法

    p.r()

1.2 写个贷款计算器

1.2.1 前端代码

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript Loan Calculator</title>
    <style>
      .output {
        font-weight: bold;
        #payment {
          text-decoration: underline;
        }
        #graph {
          border: solid black 1px;
        }
        th,
        td {
          vertical-align: top;
        }
      }
    </style>
  </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" onchange="calculate();" /></td>
      </tr>

      <tr>
        <td>Zipcode(to fnd 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 fne lenders:
          <div id="lenders"></div>
        </td>
      </tr>
    </table>
    <script>
      'use script'; //如果浏览器支持开启ECMAScript 5严格模式
      /**这里的脚本定义了caculate()函数,在HTML代码中绑定事件处理程序时会调用它丰这个函数从<input>元素中读取数据,计算贷款赔付信息,并将结果显示在<span>元素中*同样,这里还保存了用户数据、展示了放贷人链接并绘制出了图表*/
      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');
        //假设所有的输入都是合法的,将从input元素中获取输入数据
        //将百分比格式转换为小数格式,并从年利率转换为月利率
        //将年度赔付转换为月度赔付
        var principal = parseFloat(amount.value);
        var interest = parseFloat(apr.value) / 100 / 12;
        var payments = parseFloat(years.value) * 12;
        //现在计算月度赔付的数据
        var x = Math.pow(1 + interest, payments); // Math.pow()进行幂次运算
        var monthly = (principal * x * interest) / (x - 1);
        //如果结果没有超过JavaScript能表示的数字范围,且用户的输入也正确
        //这里所展示的结果就是合法的
        if (isFinite(monthly)) {
          //将数据填充至输出字段的位置,四舍五入到小数点后两位数字
          payment.innerHTML = monthly.toFixed(2);
          total.innerHTML = (monthly * payments).toFixed(2);
          totalinterest.innerHTML = (monthly * payments - principal).toFixed(2);
          //将用户的输入数据保存下来,这样在下次访问时也能取到数据
          save(amount.value, apr.value, years.value, zipcode.value);
          //找到并展示本地放贷人,但忽略网络错误
          try {
            // 捕获这段代码抛出的所有异常
            getLenders(amount.value, apr.value, years.value, zipcode.value);
          } catch (e) {
            /*忽略这些异常 */
            console.log(e);
          }
          //最后,用图表展示贷款余额、利息和资产收益
          chart(principal, interest, monthly, payments);
        } else {
          //计算结果不是数字或者是无穷大,意味着输入数据是非法或不完整的
          //清空之前的输出数据
          payment.innerHTML = ''; // 清空元素的文本内容
          total.innerHTML = '';
          totalinterest.innerHTML = '';
          chart(); //不传参数的话就是清除图表
        }
      }
      //将用户的输入保存至1ocalstorage对象的属性中
      //这些属性在再次访间时还会继续保持在原位置
      //如果你在浏览器中按照fle://URL的方式直接打开本地文件,
      //则无法在某些浏览器中使用存储功能(比如FireFox)
      //而通过HTTP打开文件是可行的
      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 =
          'http://127.0.0.1:8080/getlenders.php' + //处理数据的URL地址
          '?amt=' +
          encodeURIComponent(amount) + // 使用查询串中的数据
          '&apr=' +
          encodeURIComponent(apr) +
          '&yrs=' +
          encodeURIComponent(years) +
          '&zip=' +
          encodeURIComponent(zipcode);

        //通过XMLHttpRequest对象来提取返回数据
        var xhttp = new XMLHttpRequest(); //发起一个新的请求
        xhttp.open('GET', url); // 通过URL发起一个HTTP GET请求
        xhttp.send(null); //不带任何正文发送这个请求

        //在返回数据之前,注册了一个事件处理函数,这个处理的数
        //将会在服务器的响应返回至客户端的时候调用
        //这种异步编程模型在客户端]avascript中是非常常见的
        xhttp.onreadystatechange = function () {
          if (xhttp.readyState == 4 && xhttp.status == 200) {
            //如果代码运行到这里,说明我们得到了一个合法且完整的HTTP响应
            var response = xhttp.responseText; // HTTP响应是以字符串的形式呈现的
            var lenders = JSON.parse(response); //将其解析为]S数组
            //将数组中的放贷人对象转换为HTML字符串形式
            var list = '';
            for (var 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(principal, 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,
          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.fillText('Total Interest Payments', 20, 20); //将文字绘制到图例中
        //很多资产数据并不是线性的,很难将其反映至图表中
        var equity = 0;
        g.beginPath(); //开始绘制新图形

        g.moveTo(paymentToX(0), amountToY(0)); // 从左下方开始
        for (var p = 1; p <= payments; p++) {
          //计算出每一笔赔付的利息
          var thisMonthsInterest = (principal - 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('Total Equity', 20, 35); //文本颜色设置为绿色

        //再次循环,余额数据显示为黑色粗线条
        var bal = principal;
        g.beginPath();
        g.moveTo(paymentToX(0), amountToY(bal));
        for (varp = 1; p <= payments; 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); // 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('Year', x, y - 5); //在坐标轴做标记
          if (year % 5 == 0 && year * 12 !== payments)
            //每5年的数据
            g.fillText(string(year), x, y - 5);
        }

        //将赔付数额标记在右边界
        g.textAlign = 'right'; //文字右对齐
        g.textBaseline = 'middle'; //文字垂直居中
        var ticks = [monthly * payments, principal]; //我们将要用到的两个点
        var rightEdge = paymentToX(payments); // 设置X坐标
        for (var 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
          );
        }
      }
    </script>
  </body>
</html>

1.2.2 后端代码

1.2.2.1 后端控制层

package xm.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author heliming
 * @version 1.0
 * @date 2024/4/30-19:29
 * @description TODO
 */
@RestController
public class HelloController {

  //http://getlenders.php/?amt=100&apr=2&yrs=20&zip=23
  //  lenders[i].url +
  //                "'>" +
  //                lenders[i].name +

  @GetMapping("getlenders.php")
  public List<Map<String, String>> hello(Integer amt, Integer apr, Integer yrs,  Integer zip) {
    List<Map<String, String>> result = new ArrayList<>();
    Map<String, String> obj1 = new HashMap<>();
    obj1.put("url", "https://www.baidu.com");
    obj1.put("name", "百度");
    result.add(obj1);
    Map<String, String> obj2 = new HashMap<>();
    obj2.put("url", "https://www.taobao.com");
    obj2.put("name", "淘宝");
    result.add(obj2);
    System.out.println(result);
    return result;
  }
}

1.2.2.1 后端解决跨域

package xm.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
        .allowedOrigins("*") // 允许的前端域名或地址
        .allowedMethods("GET", "POST") // 允许的请求方法
        .allowedHeaders("*") // 允许的请求头
        .allowCredentials(true) // 允许携带凭证(如Cookie)
        .maxAge(3600); // 缓存预检请求的时间,单位秒
  }
}

1.2.3 图片


版权属于:阿明 所有,采用《知识共享署名许可协议》进行许可,转载请注明文章来源。

本文链接: http://520code.net/index.php/archives/8/

赞 (1)

评论区(暂无评论)

这里空空如也,快来评论吧~

我要评论