基于Flot可放缩的折线图
Flot初步
Flot是一个免费开源的图标插件,可以用它开发出功能强大的图表系统。下面着重讲解在Asp.net中如何使用这个插件做出功能强大的图表应用。
关于Flot,可以在这里查看现有的例子(或者是这里的例子),可以在这里查看现有的API。Flot的官方页面在这里,在里面我们可以下载需要使用的插件。下面一段话是摘自Flot官网,藉此对Flot有个初步的映像:
Flot is a pure JavaScript plotting library for jQuery, with a focus on simple usage, attractive looks and interactive features.
Works with Internet Explorer 6+, Chrome, Firefox 2+, Safari 3+ and Opera 9.5+
下面就开始我们的讲解吧。
项目讲解
首先,这是我前台的HTML部分:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ChartDaemon.aspx.cs" Inherits="NXT_YMSYS.ChartDaemon" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
body
{
background-color:#ECFBFE;
}
</style>
<link href="Scripts/flot/jquery.jqplot.css" rel="stylesheet" type="text/css" />
<script src="Scripts/flot/excanvas.min.js" type="text/javascript"></script>
<script src="Scripts/flot/jquery.min.js" type="text/javascript"></script>
<script src="Scripts/flot/jquery.flot.js" type="text/javascript"></script>
<script src="Scripts/flot/jquery.flot.time.min.js" type="text/javascript"></script>
<script src="Scripts/flot/jquery.flot.selection.min.js" type="text/javascript"></script> <script language="javascript" type="text/javascript">
var line1, line2, line3, line4, line5, line6, line7, line8;
var time="<%=time %>";
var m_sDPID = "<%=m_sDPID %>";
var min = "<%=min %>";
var max = "<%=max %>";
$(document).ready(function () {
//alert(time + "---" + m_sDPID);
if (time == "") time = "2013-10-08";
if (m_sDPID == "") m_sDPID = "103";
if (min == "") min = "0";
if (max == "") max = "0";
triggerAjaxForChart();
});
//时间改变
function triggerAjaxForChart() {
$.ajax({
url: "Handler/FlotHandlerEx.ashx?date=" + time + "&msid=" + m_sDPID + "&min=" + min + "&max=" + max,
success: function (data) {
var str = data;
// line1 = eval(str);
var arrStr = str.split("|");
line1 = eval(arrStr[0]); //当前值
line2 = eval(arrStr[1]); //min value
line3 = eval(arrStr[2]); //max value
//数据
var dataDetail = [{
label: "当前温度值",
data: line1,
color: "#1AC7F1",
lines:{ show: true, lineWidth: 3 },
shadowSize: 5,
points: { show: true, fillColor: "#fff" }
}, {
label: "最小温度值",
data: line2,
color: "#b55e00",
lines: { show: true, lineWidth: 1 },
shadowSize: 0,
points: { show: false, fillColor: "#fff" }
}, {
label: "最大温度值",
data: line3,
color: "#b55e01",
lines: { show: true, lineWidth:1 },
shadowSize: 0,
points: { show: false, fillColor: "#fff" }
}];
TriggerChart(dataDetail);
},
error: function (data) {
}
});
} //Flot chart 的具体设置
var TriggerChart = function (dataDetail) {
//-------------------------------以下部分,不需要管理-----------------
//要显示的细节设置
var detailOptions = {
series: {
lines: { show: true, lineWidth: 2 },
points: { show: false, fillColor: "#fff" },
shadowSize: 1
},
grid: {
hoverable: true,
backgroundColor: { colors: ["#ECFBFE", "#ffffff"] }
},
yaxes: {
color: "#B8E2F8"
},
yaxis: {
min: -40, //固定最小值
max: 40 //固定最大值
},
xaxis: {
mode: "time", //x轴是时间格式
color: "#B8E2F8"
},
selection: {
mode: "x"
},
legend:{
labelBoxBorderColor:"#1AC7F1"
}
}; //-----------------实现点选的部分------------------------------------------------
var choiceContainer = $("#choices");
$("#choices input").remove();
$("#choices label").remove();
plotAccordingToChoices(dataDetail, detailOptions);
$("#detailContainer").UseTooltip();
} var plotAccordingToChoices = function (dataDetail, detailOptions) {
var data = [];
data.push(dataDetail[0]);
data.push(dataDetail[1]);
data.push(dataDetail[2]); //data中保存了选中的线条
if (data.length > 0) {
//绑定选中的数据
$.plot("#detailContainer", data, detailOptions); //绑定数据的缩放
$("#detailContainer").bind("plotselected", function (event, ranges) {
plotDetail = $.plot($("#detailContainer"), data, $.extend(true, {}, detailOptions, { xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to} }));
}); //绑定右键恢复数据
$("#detailContainer").live("mousedown", function (e) {
if (event.button == 2) {
var plotDetail = $.plot($("#detailContainer"), data, detailOptions);
}
});
}
} var previousPoint = null, previousLabel = null;
$.fn.UseTooltip = function () {
$(this).bind("plothover", function (event, pos, item) {
if (item) {
if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
previousPoint = item.dataIndex;
previousLabel = item.series.label;
$("#tooltip").remove(); var x = item.datapoint[0];
var y = item.datapoint[1];
var date = new Date(x);
var color = item.series.color; if (color == "#b55e00") { //最小值
showTooltip(item.pageX, item.pageY, color,
"温度最小值为: <strong>" + y + "</strong> (℃)");
}
else if (color == "#b55e01") { //最大值
showTooltip(item.pageX, item.pageY, color,
"温度最大值为: <strong>" + y + "</strong> (℃)");
}
else {
showTooltip(item.pageX, item.pageY, color,
"<strong>" + item.series.label + "</strong><br>" +
(date.getMonth() + 1) + "月" + date.getDate() + "日" + date.getUTCHours() + "时" + date.getMinutes() + "分" +
" 温度: <strong>" + y + "</strong> (℃)");
}
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
}; function showTooltip(x, y, color, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y - 40,
left: x - 120,
border: '2px solid ' + color,
padding: '3px',
'font-size': '12px',
'border-radius': '5px',
'background-color': 'wheat',
'font-family': '宋体,Verdana, Arial, Helvetica, Tahoma, sans-serif',
opacity: 0.9
}).appendTo("body").fadeIn(200);
}
</script> </head>
<body>
<div id="example-section32" style="background-color:#EDFBFE;width:100%; float:left;" >
<div id="choices" style="width:100%;float:left; text-align:left; font-size:10pt;font-weight:normal;margin-left:18px;"></div>
<div id="detailContainer" style="height:240px; width:600px;float:left;" oncontextmenu="return false" ></div>
</div>
</body>
</html>
其次,这是我Handler中的代码部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration; namespace NXT_YMSYS.Handler
{
/// <summary>
/// FlotHandlerEx 的摘要说明
/// </summary>
public class FlotHandlerEx : IHttpHandler
{ public bool IsReusable { get { return false; } } private string connStr = ConfigurationManager.AppSettings["ConnectionString"]; public void ProcessRequest(HttpContext context)
{
string date = context.Request["date"];
if (string.IsNullOrEmpty(date))
date = "2012-12-10"; string min = context.Request["min"];
string max = context.Request["max"]; //获取对应的列
DataSet dsMap = new DataSet();
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
string querySQL = @"
select *,replace(
P_data5,P_data5,case p_data5 when '一路温度' then 'tempOne'
when '二路温度' then 'tempTwo'
when '三路温度' then 'tempThree'
when '四路温度' then 'tempFour'
when '五路温度' then 'tempFive'
when '六路温度' then 'tempSix'
when '七路温度' then 'tempSeven'
when '八路温度' then 'tempEight'
end ) result
from TB05 where p_data1='" + context.Request["msid"] + "' ";
SqlCommand cmd = new SqlCommand(querySQL, conn);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(dsMap);
} //获取对应的数据
DataSet ds = null;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
ds = new DataSet();
string sql = @"select TB04.P_data1 as tempOne,
TB04.P_data2 as tempTwo,
TB04.P_data3 as tempThree,
TB04.P_data4 as tempFour,
TB04.P_data5 as tempFive,
TB04.P_data6 as tempSix,
TB04.P_data9 as tempSeven,
TB04.P_data10 as tempEight,
(CONVERT(varchar(20), TB04.P_data7, 120)) as GetTime
from TB04 inner join TB05 on TB04.P_data8 = TB05.P_data2
where TB05.P_data1 = '" + context.Request["msid"] + @"'
and convert(date,TB04.P_data7)='" + date + @"'
-- and TB04.P_data1 not like '%F%'
order by TB04.P_data7"; SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(ds);
} if (ds.Tables[].Rows.Count <= )
{
context.Response.Write("[[" + DateTime.Parse(date).Subtract(new DateTime(, , )).TotalMilliseconds + ",0]]|[[" +
DateTime.Parse(date).Subtract(new DateTime(, , )).TotalMilliseconds + ",0]]");
return;
} //context.Response.Write("got it."); StringBuilder builder1 = new StringBuilder();
StringBuilder builder2 = new StringBuilder();
StringBuilder builder3 = new StringBuilder();
StringBuilder builder4 = new StringBuilder();
StringBuilder builder5 = new StringBuilder();
StringBuilder builder6 = new StringBuilder();
StringBuilder builder7 = new StringBuilder();
StringBuilder builder8 = new StringBuilder(); #region comment
//builder1.Append("[");
//builder2.Append("[");
//foreach (DataRow dr in ds.Tables[0].Rows)
//{
// builder1.Append("[");
// //builder1.Append("gd("+DateTime.Parse(dr["GetTime"].ToString()).ToString("yyyy,MM,dd,hh,mm,ss")+")");
// builder1.Append(DateTime.Parse(dr["GetTime"].ToString()).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds);
// builder1.Append(",");
// builder1.Append(dr["tempOne"].ToString());
// builder1.Append("],"); // builder2.Append("[");
// //builder2.Append("gd(" + DateTime.Parse(dr["GetTime"].ToString()).ToString("yyyy,MM,dd,hh,mm,ss") + ")");
// builder2.Append(DateTime.Parse(dr["GetTime"].ToString()).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds);
// builder2.Append(",");
// builder2.Append(dr["tempTwo"].ToString());
// builder2.Append("],");
//}
//string builder1Str = builder1.ToString().Substring(0, builder1.ToString().Length - 1) + "]";
//string builder2Str = builder2.ToString().Substring(0, builder2.ToString().Length - 1) + "]";
#endregion string mapColumnName = string.Empty;
if (dsMap == null) mapColumnName = "tempOne";
if (dsMap != null && dsMap.Tables[].Rows.Count == ) mapColumnName = "tempOne";
if (dsMap != null && dsMap.Tables[].Rows.Count > ) mapColumnName = dsMap.Tables[].Rows[]["result"].ToString(); string builder1Str = ConstructSBuilder(builder1, ds, mapColumnName);
string buildMinStr = ConstructSBuilder(builder2, ds, mapColumnName, float.Parse(min).ToString("0.0"));
string buildMaxStr = ConstructSBuilder(builder3, ds, mapColumnName, float.Parse(max).ToString("0.0"));
//string builder2Str = ConstructSBuilder(builder2, ds, "tempTwo");
//string builder3Str = ConstructSBuilder(builder3, ds, "tempThree");
//string builder4Str = ConstructSBuilder(builder4, ds, "tempFour");
//string builder5Str = ConstructSBuilder(builder5, ds, "tempFive");
//string builder6Str = ConstructSBuilder(builder6, ds, "tempSix");
//string builder7Str = ConstructSBuilder(builder7, ds, "tempSeven");
//string builder8Str = ConstructSBuilder(builder8, ds, "tempEight"); // context.Response.Write(builder1Str + "|" + builder2Str + "|" + builder3Str + "|" + builder4Str + "|" + builder5Str + "|" + builder6Str + "|" + builder7Str + "|" + builder8Str);
context.Response.Write(builder1Str + "|" + buildMinStr + "|" + buildMaxStr);
} private string ConstructSBuilder(StringBuilder builder, DataSet ds, string rowFilled,string value)
{
builder.Append("[");
foreach (DataRow dr in ds.Tables[].Rows)
{
string result = dr[rowFilled].ToString();
if (!result.ToUpper().Equals("FF.F"))
{
builder.Append("[");
//builder1.Append("gd("+DateTime.Parse(dr["GetTime"].ToString()).ToString("yyyy,MM,dd,hh,mm,ss")+")");
builder.Append(DateTime.Parse(dr["GetTime"].ToString()).Subtract(new DateTime(, , )).TotalMilliseconds);
builder.Append(",");
builder.Append(value);
builder.Append("],");
}
}
string builderStr = builder.ToString().Substring(, builder.ToString().Length - ) + "]";
return builderStr;
} private string ConstructSBuilder(StringBuilder builder, DataSet ds, string rowFilled)
{
builder.Append("[");
foreach (DataRow dr in ds.Tables[].Rows)
{
string result = dr[rowFilled].ToString();
if (!result.ToUpper().Equals("FF.F"))
{
builder.Append("[");
//builder1.Append("gd("+DateTime.Parse(dr["GetTime"].ToString()).ToString("yyyy,MM,dd,hh,mm,ss")+")");
builder.Append(DateTime.Parse(dr["GetTime"].ToString()).Subtract(new DateTime(, , )).TotalMilliseconds);
builder.Append(",");
builder.Append(result);
builder.Append("],");
}
}
string builderStr = builder.ToString().Substring(, builder.ToString().Length - ) + "]";
return builderStr;
}
}
}
首先,针对前台部分,我们需要注意几个东西,第一个是Flot数据的组织方式;其次是折线如何配置并显示;再者就是如何实现放大缩小;最后就是如何显示ToolTip。
数据的组织方式,通过查看API文档,我们发现,Flot线条的数据组织方式如下[[x轴显示的值,Y轴显示的值],[x轴显示的值,Y轴显示的值]…..],也就就是
[[x1,y1],[x2,y2],...]的组织方式,所以在后台,我也是用这种方式来组织数据的。需要说明下,如果x轴是时间轴的话,我们需要计算从现在时间到1970年1月1日所有微秒的和,用C#表示就是:
builder.Append(DateTime.Parse(dr["GetTime"].ToString()).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds);
折线如何配置并显示呢?这个通过API文档,我们发现数据是这样组织的:
{
color: color or number //线条颜色
data: rawdata //你从后台拼接的数据,例如刚刚说的[[x1,y1],[x2,y2]...]
label: string //标签文本,描述你的线条的名称
lines: specific lines options //设置线条属性,比如lines:{ show: true, lineWidth: 3 }
bars: specific bars options //同上
points: specific points options //每个数据点的属性,比如points: { show: true, fillColor: "#fff" }
xaxis: number //x轴属性
yaxis: number //y轴属性
clickable: boolean //是否可点击
hoverable: boolean //是否可悬停
shadowSize: number //阴影效果
}
看完这个,你再看看我HTML代码中的设置,是不是恍然大悟呢?
$.ajax({
url: "Handler/FlotHandlerEx.ashx?date=" + time + "&msid=" + m_sDPID + "&min=" + min + "&max=" + max,
success: function (data) {
var str = data;
// line1 = eval(str);
var arrStr = str.split("|");
line1 = eval(arrStr[0]); //当前值
line2 = eval(arrStr[1]); //min value
line3 = eval(arrStr[2]); //max value
//Flot数据,注意其数据格式
var dataDetail = [{
label: "当前温度值",
data: line1,
color: "#1AC7F1",
lines:{ show: true, lineWidth: 3 },
shadowSize: 5,
points: { show: true, fillColor: "#fff" }
}, {
label: "最小温度值",
data: line2,
color: "#b55e00",
lines: { show: true, lineWidth: 1 },
shadowSize: 0,
points: { show: false, fillColor: "#fff" }
}, {
label: "最大温度值",
data: line3,
color: "#b55e01",
lines: { show: true, lineWidth:1 },
shadowSize: 0,
points: { show: false, fillColor: "#fff" }
}];
TriggerChart(dataDetail);
},
error: function (data) {
}
});
数据组织好以后,利用Flot自带的函数 $.plot("#detailContainer", data, detailOptions); 就可以将指定的数据绑定到界面了。需要说明的是detailOptions是指整个图标的全局设置,包括y轴最大值,最小值,图表背景色等等,可以参阅HTML源码部分。
然后就是实现放大缩小功能了。由于在例子中,已经提供了说明,所以,我打开了例子的源码,研究了之后,发现要实现放大缩小还是很简单的。利用其提供的plotselected方法即可。
//绑定数据的缩放
$("#detailContainer").bind("plotselected", function (event, ranges) {
plotDetail = $.plot($("#detailContainer"), data, $.extend(true, {}, detailOptions, { xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to} }));
});
其中,$.extend(true, {}, detailOptions, { xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to} })是关键点。
最后就是显示ToolTip(注意,由于本人美工较差,ToolTip外形效果来自网上)功能了,因为Flot中提供了当前鼠标悬停的点的位置,所以我们可以通过编写函数来实现悬停效果:
var previousPoint = null, previousLabel = null;
$.fn.UseTooltip = function () {
$(this).bind("plothover", function (event, pos, item) {
if (item) {
if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
previousPoint = item.dataIndex;
previousLabel = item.series.label;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var date = new Date(x);
var color = item.series.color;
if (color == "#b55e00") { //最小值
showTooltip(item.pageX, item.pageY, color,
"温度最小值为: <strong>" + y + "</strong> (℃)");
}
else if (color == "#b55e01") { //最大值
showTooltip(item.pageX, item.pageY, color,
"温度最大值为: <strong>" + y + "</strong> (℃)");
}
else {
showTooltip(item.pageX, item.pageY, color,
"<strong>" + item.series.label + "</strong><br>" +
(date.getMonth() + 1) + "月" + date.getDate() + "日" + date.getUTCHours() + "时" + date.getMinutes() + "分" +
" 温度: <strong>" + y + "</strong> (℃)");
}
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
};
function showTooltip(x, y, color, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y - 40,
left: x - 120,
border: '2px solid ' + color,
padding: '3px',
'font-size': '12px',
'border-radius': '5px',
'background-color': 'wheat',
'font-family': '宋体,Verdana, Arial, Helvetica, Tahoma, sans-serif',
opacity: 0.9
}).appendTo("body").fadeIn(200);
}
后台代码我就不讲解了,没什么实际意义,只要按照API文档组织好数据,就没有什么问题,下面看下效果图:
效果展示
(图1,正常浏览)
(图2,选择浏览范围)
(图3,浏览范围选择完毕,自动放大)
(图4,ToolTip效果展示)
当然了,如果你有多条线的情况下,你还可以通过选中或者是不选中CheckBox先展示一部分数据,只需要将代码修改成如下结构即可:
效果如下图:
(图5,全部选中)
(图5,只选中空气湿度和土壤温度)
代码下载
基于Flot可放缩的折线图的更多相关文章
- Morris.js和flot绘制折线图的比较
[文章摘要] 最近用开源的AdminLTE做框架感觉效果特别好,其针对图表库Morris.js和flot都提供了不错的支持,也都提供了这两者的例子.不过Morris.js是基于Raphael.js来的 ...
- python3绘图示例3(基于matplotlib:折线图等)
#!/usr/bin/env python# -*- coding:utf-8 -*-from pylab import *from numpy import *import numpy # 数据点图 ...
- 基于SpringMVC框架使用ECharts3.0实现折线图,柱状图,饼状图,的绘制(上篇)
页面部分 <%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE html> ...
- 前端数据统计用做Bootstrap的一些柱状图、饼状图和折线图案例
Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷. Bootstrap ...
- Aristochart – 灵活的 HTML5 Canvas 折线图
Aristochart 是基于 HTML5 Canvas 的折线图功能库,具有高定制性和灵活性的特点.Aristochart 会帮助你处理图形显示,让你能够专注于业务逻辑处理. 您可能感兴趣的相关文章 ...
- GNUPLOT 画多组柱状图 以及 折线图 以及各种问题的解决方案
在Windows下使用客户端,直接可以打开.plt文件的gnuplot格式的文件,open->xx.plt 在Linux下使用shell 运行gnuplot脚本, 结果一闪而过.解决办法是在 程 ...
- 百度推出的echarts,制表折线图柱状图饼图等的超级工具(转)
一.简介: 1.绘制数据图表,有了它,想要网页上绘制个折线图.柱状图,从此easy. 2.使用这个百度的echarts.js插件,是通过把图片绘制在canvas上在显示在页面上. 官网对echarts ...
- echarts折线图--数据交互
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 9款基于HTML5/SVG/Canvas的折线图表应用
1.华丽的HTML5图表 可展示实时数据 HTML5在图表应用中也十分广泛,比起以前的网页图表,HTML5图表制作更便捷,功能更强大.这款HTML5图表插件外观十分华丽和专业,在数据展示方面也很有优势 ...
随机推荐
- 【原/转】【boost】智能指针使用规则以及介绍
智能指针机制跟Objective-C里面的retainCount引用计数有着相同的原理,当某个对象的引用计数为0是执行delete操作,类似于autorelease 初学者在使用智能指针时,很多情况下 ...
- sgu 104 Little shop of flowers 解题报告及测试数据
104. Little shop of flowers time limit per test: 0.25 sec. memory limit per test: 4096 KB 问题: 你想要将你的 ...
- (ios实战)ios调试总结(转载)
在程序中,无论是你想弄清楚为什么数组中有3个对象而不是5个,或者为什么一个新的玩家开始之后,游戏在倒退——调试在这些处理过程中是比较重要的一部分.通过本文的学习,我们将知道在程序中,可以使用的大多数重 ...
- Java 图片处理——如何生成高清晰度而占有磁盘小的缩略图
现在的web项目,图片越来越多,图片大小也越来越大,随便就能达到1M,2M,甚至更大.用户上传的图片,一般是无法直接使用的.一般要生成两三种对应的缩略图,分别适配不同的终端,不同的场景.比如PC,手机 ...
- Java 8 LongAdders:管理并发计数器的正确方式
转自:http://www.importnew.com/11345.html 我只是喜欢新鲜的事物,而Java 8 有很多新东西.这次我想讨论其中我最喜欢的之一:并发加法器.这是一个新的类集合,他们用 ...
- c#发送http请求
直接代码,自己备用 /** * @method:生成验证码 */ [JSONMethod] [Description ( "生成验证码" )] [DomTemplate ( )] ...
- C++find函数
头文件 #include <algorithm> 函数实现 template<class InputIterator, class T> InputIterator find ...
- 动手学习TCP:服务端状态变迁
上一篇文章介绍了TCP状态机,并且通过实验了解了TCP客户端正常的状态变迁过程. 那么,本篇文章就一起看看TCP服务端的正常状态变迁过程 服务端状态变迁 根据上一篇文章中的TCP状态变迁图,可以得到服 ...
- hdu-5496 Beauty of Sequence(递推)
题目链接: Beauty of Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java ...
- 如何禁止 iPhone Safari video标签视频自动全屏?
最近做一个移动端微信页面项目,在微信页面中有视频播放,但是需要禁止IOS的自动全屏播放(前提必须使用video标签).如: <video id="post" autoplay ...