习题解答
这道题考的是 HTML5 的拖放 API。就像你在淘宝把商品拖进购物车一样——先让商品图片"可以被拖"(draggable="true"),再让购物车区域"允许接收"(监听 dragover 和 drop 事件)。
从效果图可以看出:
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML 5中的拖放</title>
<style>
body {
font-family: "Microsoft YaHei", sans-serif;
margin: 0;
padding: 0;
}
/* 两栏布局:商品列表 + 购物车 */
.container {
display: flex;
width: 100%;
min-height: 300px;
}
/* 左侧商品列表 */
#product-list {
width: 50%;
background: #d9d9d9;
padding: 15px;
box-sizing: border-box;
}
/* 右侧购物车 */
#cart {
width: 50%;
background: #d9d9d9;
padding: 15px;
box-sizing: border-box;
border-left: 1px solid #bbb;
}
h2 {
font-size: 1.2rem;
font-weight: bold;
margin: 0 0 10px 0;
padding-bottom: 8px;
border-bottom: 1px solid #999;
}
/* 商品图片样式 */
.product-img {
width: 100px;
height: 130px;
object-fit: cover;
margin: 5px;
cursor: grab;
border: 2px solid transparent;
transition: border-color 0.2s;
}
.product-img:hover {
border-color: #666;
}
/* 拖放目标区域高亮 */
#cart.drag-over {
background: #c8e6c9;
border: 2px dashed #4caf50;
}
</style>
</head>
<body>
<div class="container">
<!-- 左侧:商品列表 -->
<div id="product-list">
<h2>商品列表</h2>
<!-- draggable="true" 使图片可以被拖动 -->
<img class="product-img" src="images/girl1.jpg"
draggable="true"
ondragstart="dragStart(event)"
alt="商品1">
<img class="product-img" src="images/girl2.jpg"
draggable="true"
ondragstart="dragStart(event)"
alt="商品2">
<img class="product-img" src="images/girl3.jpg"
draggable="true"
ondragstart="dragStart(event)"
alt="商品3">
</div>
<!-- 右侧:购物车 -->
<div id="cart"
ondragover="dragOver(event)"
ondragleave="dragLeave(event)"
ondrop="drop(event)">
<h2>购物车</h2>
</div>
</div>
<script type="text/javascript">
// 拖动开始:记录被拖动图片的 src
function dragStart(event) {
// 把被拖动元素的 outerHTML 存入 dataTransfer
event.dataTransfer.setData("text/html", event.target.outerHTML);
event.dataTransfer.effectAllowed = "copy";
}
// 拖动悬停在目标上:必须阻止默认行为,否则无法触发 drop
function dragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = "copy";
document.getElementById("cart").classList.add("drag-over");
}
// 拖动离开目标区域:取消高亮
function dragLeave(event) {
document.getElementById("cart").classList.remove("drag-over");
}
// 放下:把图片克隆到购物车中
function drop(event) {
event.preventDefault();
var cart = document.getElementById("cart");
cart.classList.remove("drag-over");
// 取出之前保存的 HTML 内容
var imgHtml = event.dataTransfer.getData("text/html");
// 创建一个临时容器来解析 HTML
var temp = document.createElement("div");
temp.innerHTML = imgHtml;
var img = temp.firstChild;
// 调整样式后插入购物车
img.style.margin = "5px";
cart.appendChild(img);
}
</script>
</body>
</html>
代码要点说明:
draggable="true",这是启用拖放的第一步。ondragstart:拖动开始时,用 dataTransfer.setData() 把图片的 HTML 内容存起来,相当于"复制到剪贴板"。ondragover:必须调用 event.preventDefault(),否则浏览器会拒绝 drop 事件(默认不允许放置)。ondrop:用 dataTransfer.getData() 取出内容,插入购物车容器中。📖 参见 11.1 拖放、11.1.1 draggable属性、11.1.2 拖放事件、11.1.3 dataTransfer对象
这道题考的是 HTML5 的 <video> 标签。HTML5 之前播放视频需要 Flash 插件,现在直接用一个标签就搞定了!效果图显示:页面标题是"播放视频",视频内容是一段海岛风光,宽度铺满页面主体,显示播放控制条(进度条、播放按钮、时间、音量、全屏按钮)。
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>视频标签video示例</title>
<style>
body {
font-family: "Microsoft YaHei", sans-serif;
margin: 0;
padding: 10px 15px;
background: #fff;
}
h2 {
font-size: 1.1rem;
font-weight: bold;
margin-bottom: 10px;
}
/* 视频元素样式:宽度撑满容器 */
video {
display: block;
width: 100%;
max-width: 700px;
background: #000;
}
</style>
</head>
<body>
<h2>播放视频</h2>
<!--
controls:显示播放控制条(播放/暂停、进度条、音量、全屏)
width:视频宽度
可选属性:
autoplay 自动播放
loop 循环播放
muted 静音
poster 封面图片
-->
<video controls width="700">
<!-- source 元素指定视频文件路径,可同时提供多种格式以兼容不同浏览器 -->
<source src="videos/beach.mp4" type="video/mp4">
<source src="videos/beach.webm" type="video/webm">
<!-- 当浏览器不支持 video 标签时显示此提示 -->
您的浏览器不支持 HTML5 video 标签,请升级浏览器。
</video>
</body>
</html>
代码要点说明:
controls 属性(布尔属性,不用赋值):显示浏览器默认的播放控制条,效果图中可以看到有播放按钮、进度条、时间显示、音量和全屏按钮。<source> 元素:推荐同时提供 MP4 和 WebM 两种格式,浏览器会自动选择自己支持的那种。type 属性:告诉浏览器视频格式,让它能快速判断是否支持,无需先下载再检测。<video> 和 </video> 之间,只在浏览器不支持时显示。autoplay(自动播放)、loop(循环)、muted(静音)、poster="封面.jpg"(视频封面图)。📖 参见 HTML5 媒体元素 <video> 标签及其 controls、src、type 属性
这道题考的是 Canvas 的路径绘图——用 arc() 和 lineTo() 画出多个扇形,拼成一张圆饼图。效果图显示:一个完整圆形被分成 5 个扇形,颜色各异(原图为彩色,在灰度截图中可见明显的明暗区分),绘制在带边框的白色 canvas 上。
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Canvas绘制圆饼图</title>
<style>
body {
font-family: "Microsoft YaHei", sans-serif;
margin: 10px;
}
canvas {
display: block;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<!-- canvas 画布:宽300,高270,加边框 -->
<canvas id="myCanvas" width="300" height="270"
style="border:1px solid #ccc;"></canvas>
<script type="text/javascript">
// 获取 canvas 元素和 2D 绘图上下文
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// 圆饼图的数据:各扇形占比(百分比,合计100)
var data = [30, 15, 25, 20, 10]; // 5个数据项
// 对应的填充颜色(5种颜色)
var colors = [
"#e74c3c", // 红
"#3498db", // 蓝
"#2ecc71", // 绿
"#f39c12", // 橙
"#9b59b6" // 紫
];
// 圆心坐标和半径
var cx = 150; // 圆心 X
var cy = 135; // 圆心 Y
var radius = 110; // 半径
// 起始角度:从正上方(-90度,即 -π/2)开始,习惯上饼图从12点钟方向开始
var startAngle = -Math.PI / 2;
// 计算数据总和
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i];
}
// 逐个绘制扇形
for (var i = 0; i < data.length; i++) {
// 当前扇形的弧度 = (当前数据 / 总数) * 2π
var sliceAngle = (data[i] / total) * 2 * Math.PI;
var endAngle = startAngle + sliceAngle;
ctx.beginPath();
// 移动到圆心
ctx.moveTo(cx, cy);
// 画弧线(顺时针方向)
ctx.arc(cx, cy, radius, startAngle, endAngle, false);
// 连线回到圆心,形成闭合扇形
ctx.closePath();
// 设置填充颜色并填充
ctx.fillStyle = colors[i];
ctx.fill();
// 绘制白色边框线,让扇形之间有分隔
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 2;
ctx.stroke();
// 下一个扇形从当前结束角度开始
startAngle = endAngle;
}
</script>
</body>
</html>
代码要点说明:
moveTo(圆心) → arc(画弧) → closePath(连回圆心),三步构成一个封闭扇形。arc(cx, cy, r, 起始角, 结束角, 逆时针):角度以弧度为单位,0 对应3点钟方向;用 -Math.PI/2 作起点,让饼图从12点钟位置开始,更符合阅读习惯。(该项数据 / 总数据) × 2π,这是饼图的核心公式。beginPath() 每次必须调用,否则所有路径会连在一起。strokeStyle = "#ffffff")用于在扇形之间画出清晰的分隔线。📖 参见 11.2 画布(canvas)、11.2.4 绘制路径(arc方法)、11.2.5 绘制样式(fillStyle/fill)
这道题考的是 HTML5 的地理定位 API(Geolocation API)。就像手机地图的"我的位置"功能——浏览器会先问用户"是否允许获取你的位置",用户同意后才能拿到经纬度数据。
实现思路:
navigator.geolocation 判断浏览器是否支持地理定位。alert() 提示"支持地理定位"。navigator.geolocation.getCurrentPosition() 获取位置。position.coords.latitude(纬度)和 position.coords.longitude(经度),用 alert() 显示出来。完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5地理定位</title>
</head>
<body>
<h3>HTML5 Geolocation 地理定位示例</h3>
<button onclick="getLocation()">获取我的位置</button>
<p id="result"></p>
<script type="text/javascript">
function getLocation() {
// 第一步:检测浏览器是否支持 Geolocation API
if (navigator.geolocation) {
// 支持:弹出提示框
alert("您的浏览器支持地理定位!");
// 用户点击"确定"后,请求获取当前位置
// getCurrentPosition() 是异步的,成功时调用 showPosition,失败时调用 showError
navigator.geolocation.getCurrentPosition(showPosition, showError);
} else {
// 不支持:提示升级
alert("您的浏览器不支持地理定位功能,请升级浏览器!");
}
}
// 获取位置成功的回调函数
// position 对象包含 coords(坐标信息)和 timestamp(时间戳)
function showPosition(position) {
var lat = position.coords.latitude; // 纬度
var lng = position.coords.longitude; // 经度
// 弹出消息框显示经纬度
alert("当前位置:\n纬度(latitude)= " + lat + "\n经度(longitude)= " + lng);
// 也可以在页面中显示
document.getElementById("result").innerHTML =
"纬度:" + lat.toFixed(6) + "<br>经度:" + lng.toFixed(6);
}
// 获取位置失败的回调函数(用户拒绝授权或定位超时等)
function showError(error) {
switch(error.code) {
case error.PERMISSION_DENIED:
alert("用户拒绝了地理定位请求。");
break;
case error.POSITION_UNAVAILABLE:
alert("位置信息不可用。");
break;
case error.TIMEOUT:
alert("请求超时。");
break;
default:
alert("发生未知错误:" + error.message);
}
}
</script>
</body>
</html>
代码要点说明:
navigator.geolocation:这是浏览器内置的地理定位对象,存在则表示支持,用 if 判断即可。getCurrentPosition(成功回调, 失败回调):异步方法,浏览器会弹出"是否允许获取位置"的权限提示,用户同意后才执行成功回调。position.coords.latitude:纬度(南北方向,范围 -90° ~ 90°)。position.coords.longitude:经度(东西方向,范围 -180° ~ 180°)。file:// 协议在部分浏览器中也可以测试。📖 参见 HTML5 Geolocation API、navigator.geolocation.getCurrentPosition() 方法