博客 (18)

若在谷歌浏览器中记住密码,再次打开时,表单中自动填充的文本框和下拉框都变成了黄色背景,影响界面美观,可以使用以下样式修正:

/* Change Autocomplete styles in Chrome*/
input:-webkit-autofill,
input:-webkit-autofill:hover, 
input:-webkit-autofill:focus
input:-webkit-autofill, 
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
  border: 1px solid green;
  -webkit-text-fill-color: green;
  -webkit-box-shadow: 0 0 0px 1000px #000 inset;
  transition: background-color 5000s ease-in-out 0s;
}

具体样式请自行修改。

参考资料:https://css-tricks.com/snippets/css/change-autocomplete-styles-webkit-browsers/

xoyozo 8 年前
4,650

http://npoi.codeplex.com/documentation

免费,开源,无需安装 Office,功能强大,兼容性好,使用方便,可以在 Visual Studio 的 NuGet 管理器中直接搜索安装。

导出 Excel 简单示例:

HSSFWorkbook book = new HSSFWorkbook();
ISheet sheet = book.CreateSheet("工作表1");

IRow r0 = sheet.CreateRow(0);
r0.CreateCell(0).SetCellValue("行1列1");
r0.CreateCell(1).SetCellValue("行1列2");

IRow r1 = sheet.CreateRow(1);
r1.CreateCell(0).SetCellValue("行2列1");
r1.CreateCell(2).SetCellValue("行2列3");

MemoryStream ms = new MemoryStream();
book.Write(ms);
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", "文件名"));
Response.BinaryWrite(ms.ToArray());
Response.End();
book = null;
ms.Close();
ms.Dispose();

字体相关:

ICellStyle style = book.CreateCellStyle();
IFont font = book.CreateFont();
font.FontHeightInPoints = 20; // 字体大小
font.Color = HSSFColor.White.Index; // 字体颜色
style.SetFont(font);
style.FillForegroundColor = HSSFColor.Red.Index; // 背景色
style.FillPattern = FillPattern.SolidForeground;
cell.CellStyle = style;

合并单元格:

CellRangeAddress cra = new CellRangeAddress(r - 1, r - 1, c - 1, c);
sheet.AddMergedRegion(cra);

宽度自适应:

for (int i = 1; i < c; i++) {
  sheet.AutoSizeColumn(i);
}

函数:

cell.SetCellFormula("SUM(B2:B4)");

顺便提一句,ICellStyle 和 IFont 最好一种样式一个变量先定义好再用,不要在循环里疯狂地 Create,否则超出数量(512个)会导致样式失效。

其它参考:http://www.ez2o.com/Blog/Post/csharp-Excel-NPOI-Font-Style

 

 

xoyozo 8 年前
6,183

tgideas-html5-api-test-1-1

编者按:今天腾讯万技师同学的这篇技术总结必须强烈安利下,目录清晰,层次分明,每个接口都有对应的简介、系统要求、实例、核心代码以及超实用的思维发散,帮你直观把这些知识点get起来。以现在HTML 5的势头,同志们,你看到的这些,可都是钱呐。

十二年前,无论多么复杂的布局,在我们神奇的table面前,都不是问题;

十年前,阿捷的一本《网站重构》,为我们开启了新的篇章;

八年前,我们研究yahoo.com,惊叹它在IE5下都表现得如此完美;

六年前,Web标准化成了我们的基础技能,我们开始研究网站性能优化;

四年前,我们开始研究自动化工具,自动化测试,谁没玩过nodejs都不好意思说是页面仔;

二年前,各种终端风起云涌,响应式、APP开发都成为了我们研究的范围,CSS3动画开始风靡;

如今,CSS3动画、Canvas、SVG、甚至webGL你已经非常熟悉,你是否开始探寻,接下来,我们可以玩什么,来为我们项目带来一丝新意?

没错,本文就是以HTML5 Device API为核心,对HTML5的一些新接口作了一个完整的测试,希望能让大家有所启发。

目录:

一、让音乐随心而动 – 音频处理 Web audio API
二、捕捉用户摄像头 – 媒体流 Media Capture
三、你是逗逼? – 语音识别 Web Speech API
四、让我尽情呵护你 – 设备电量 Battery API
五、获取用户位置 – 地理位置 Geolocation API
六、把用户捧在手心 – 环境光 Ambient Light API
七、陀螺仪 Deviceorientation
八、Websocket
九、NFC
十、震动 - Vibration API
十一、网络环境 Connection API

一、让音乐随心而动 – 音频处理 Web audio API

简介:

Audio对象提供的只是音频文件的播放,而Web Audio则是给了开发者对音频数据进行分析、处理的能力,比如混音、过滤。

系统要求:

ios6+、android chrome、android firefox

实例:

http://sy.qq.com/brucewan/device-api/web-audio.html

核心代码:

var context = new webkitAudioContext();
var source = context.createBufferSource();   // 创建一个声音源
source.buffer = buffer;   // 告诉该源播放何物 
createBufferSourcesource.connect(context.destination);   // 将该源与硬件相连
source.start(0); //播放

技术分析:

当我们加载完音频数据后,我们将创建一个全局的AudioContext对象来对音频进行处理,AudioContext可以创建各种不同功能类型的音频节点AudioNode,比如

1、源节点(source node)

我们可以使用两种方式加载音频数据:
<1>、audio标签

var sound, audio = new Audio();
audio.addEventListener('canplay', function() {
 sound = context.createMediaElementSource(audio);
 sound.connect(context.destination);
});
audio.src = '/audio.mp3';

<2>、XMLHttpRequest

var sound, context = createAudioContext();
var audioURl = '/audio.mp3'; // 音频文件URL
var xhr = new XMLHttpRequest();
xhr.open('GET', audioURL, true);
xhr.responseType = 'arraybuffer'; 
xhr.onload = function() {
 context.decodeAudioData(request.response, function (buffer) {
 source = context.createBufferSource();
 source.buffer = buffer;
 source.connect(context.destination);
 }
}
xhr.send();

2、分析节点(analyser node)

我们可以使用AnalyserNode来对音谱进行分析,例如:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);

function draw() {
 drawVisual = requestAnimationFrame(draw);
 analyser.getByteTimeDomainData(dataArray);
 // 将dataArray数据以canvas方式渲染出来
};

draw();

3、处理节点(gain node、panner node、wave shaper node、delay node、convolver node等)

不同的处理节点有不同的作用,比如使用BiquadFilterNode调整音色(大量滤波器)、使用ChannelSplitterNode分割左右声道、使用GainNode调整增益值实现音乐淡入淡出等等。

需要了解更多的音频节点可能参考:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API

4、目的节点(destination node)

所有被渲染音频流到达的最终地点

思维发散:

1、可以让CSS3动画跟随背景音乐舞动,可以为我们的网页增色不少;
2、可以尝试制作H5酷酷的变声应用,增加与用户的互动;
3、甚至可以尝试H5音乐创作。

看看google的创意:http://v.youku.com/v_show/id_XNTk0MjQyNDMy.html

二、捕捉用户摄像头 – 媒体流 Media Capture

简介:

通过getUserMedia捕捉用户摄像头获取视频流和通过麦克风获取用户声音。

系统要求:

android chrome、android firefox

实例:

捕获用户摄像头 捕获用户麦克风

http://sy.qq.com/brucewan/device-api/camera.html

http://sy.qq.com/brucewan/device-api/microphone-usermedia.html

核心代码:

1、摄像头捕捉

navigator.webkitGetUserMedia ({video: true}, function(stream) {
 video.src = window.URL.createObjectURL(stream);
 localMediaStream = stream;
}, function(e){

})

2、从视频流中拍照

btnCapture.addEventListener('touchend', function(){
	if (localMediaStream) {
		canvas.setAttribute('width', video.videoWidth);
		canvas.setAttribute('height', video.videoHeight);
		ctx.drawImage(video, 0, 0);
	}
}, false);

3、用户声音录制

navigator.getUserMedia({audio:true}, function(e) {
	context = new audioContext();
	audioInput = context.createMediaStreamSource(e);	
	volume = context.createGain();
	recorder = context.createScriptProcessor(2048, 2, 2);
	recorder.onaudioprocess = function(e){
		recordingLength += 2048;
		recorder.connect (context.destination); 
	}	
}, function(error){});

4、保存用户录制的声音

var buffer = new ArrayBuffer(44 + interleaved.length * 2);
var view = new DataView(buffer);
fileReader.readAsDataURL(blob); // android chrome audio不支持blob
… audio.src = event.target.result;

思维发散:

1、从视频拍照自定义头像;
2、H5视频聊天;
3、结合canvas完成好玩的照片合成及处理;
4、结合Web Audio制作有意思变声应用。

三、你是逗逼? – 语音识别 Web Speech API简介:

1、将文本转换成语音;
2、将语音识别为文本。

系统要求:
ios7+,android chrome,android firefox

测试实例:

http://sy.qq.com/brucewan/device-api/microphone-webspeech.html

核心代码:

1、文本转换成语音,使用SpeechSynthesisUtterance对象;

var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();
msg.volume = 1; // 0 to 1
msg.text = ‘识别的文本内容’;
msg.lang = 'en-US';
speechSynthesis.speak(msg);

2、语音转换为文本,使用SpeechRecognition对象。

var newRecognition = new webkitSpeechRecognition();
newRecognition.onresult = function(event){
	var interim_transcript = ''; 
	for (var i = event.resultIndex; i < event.results.length; ++i) {
		final_transcript += event.results[i][0].transcript;
	}
};

测试结论:

1、Android支持不稳定;语音识别测试失败(暂且认为是某些内置接口被墙所致)。

思维发散:

1、当语音识别成为可能,那声音控制将可以展示其强大的功能。在某些场景,比如开车、网络电视,声音控制将大大改善用户体验;
2、H5游戏中最终分数播报,股票信息实时声音提示,Web Speech都可以大放异彩。

 四、让我尽情呵护你 – 设备电量 Battery API简介:

查询用户设备电量及是否正在充电。

系统要求:

android firefox

测试实例:

http://sy.qq.com/brucewan/device-api/battery.html

核心代码:

var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery;
var str = '';
if (battery) {
 str += '<p>你的浏览器支持HTML5 Battery API</p>';
 if(battery.charging) {
 str += '<p>你的设备正在充电</p>';
} else {
 str += '<p>你的设备未处于充电状态</p>';
}
 str += '<p>你的设备剩余'+ parseInt(battery.level*100)+'%的电量</p>';
} else {
 str += '<p>你的浏览器不支持HTML5 Battery API</p>';
}

测试结论:

1、QQ浏览器与UC浏览器支持该接口,但未正确显示设备电池信息;
2、caniuse显示android chrome42支持该接口,实测不支持。

思维发散:

相对而言,我觉得这个接口有些鸡肋。
很显然,并不合适用HTML5做电池管理方面的工作,它所提供的权限也很有限。
我们只能尝试做一些优化用户体验的工作,当用户设备电量不足时,进入省电模式,比如停用滤镜、摄像头开启、webGL、减少网络请求等。

 五、获取用户位置 – 地理位置 Geolocation简介:

Geolocation API用于将用户当前地理位置信息共享给信任的站点,目前主流移动设备都能够支持。

系统要求:

ios6+、android2.3+

测试实例:

http://sy.qq.com/brucewan/device-api/geolocation.html

核心代码:

var domInfo = $("#info");

// 获取位置坐标
if (navigator.geolocation) {
	navigator.geolocation.getCurrentPosition(showPosition,showError);
}
else{
	domInfo.innerHTML="抱歉,你的浏览器不支持地理定位!";
}

// 使用腾讯地图显示位置
function showPosition(position) {
	var lat=position.coords.latitude;
	var lon=position.coords.longitude;

	mapholder = $('#mapholder')
	mapholder.style.height='250px';
	mapholder.style.width = document.documentElement.clientWidth + 'px';

	var center = new soso.maps.LatLng(lat, lon);
	var map = new soso.maps.Map(mapholder,{
		center: center,
		zoomLevel: 13
	});

	var geolocation = new soso.maps.Geolocation();
	var marker = null;
	geolocation.position({}, function(results, status) {
		console.log(results);
		var city = $("#info");
		if (status == soso.maps.GeolocationStatus.OK) {
			map.setCenter(results.latLng);
			domInfo.innerHTML = '你当前所在城市: ' + results.name;
		if (marker != null) {
			marker.setMap(null);
		}
		// 设置标记
		marker = new soso.maps.Marker({
			map: map,
			position:results.latLng
		});
		} else {
			alert("检索没有结果,原因: " + status);
		}
	});
}

测试结论:

1、Geolocation API的位置信息来源包括GPS、IP地址、RFID、WIFI和蓝牙的MAC地址、以及GSM/CDMS的ID等等。规范中没有规定使用这些设备的先后顺序。
2、初测3g环境下比wifi环境理定位更准确;
3、测试三星 GT-S6358(android2.3) geolocation存在,但显示位置信息不可用POSITION_UNAVAILABLE。

六、把用户捧在手心 – 环境光 Ambient Light简介:

Ambient Light API定义了一些事件,这些时间可以提供源于周围光亮程度的信息,这通常是由设备的光感应器来测量的。设备的光感应器会提取出辉度信息。

系统要求:

android firefox

测试实例:

http://sy.qq.com/brucewan/device-api/ambient-light.html

核心代码:

这段代码实现感应用前当前环境光强度,调整网页背景和文字颜色。


var domInfo = $('#info');
if (!('ondevicelight' in window)) {
	domInfo.innerHTML = '你的设备不支持环境光Ambient Light API';
} else {
	var lightValue = document.getElementById('dl-value');
	window.addEventListener('devicelight', function(event) {
		domInfo.innerHTML = '当前环境光线强度为:' + Math.round(event.value) + 'lux';
		var backgroundColor = 'rgba(0,0,0,'+(1-event.value/100) +')';
		document.body.style.backgroundColor = backgroundColor;
		if(event.value < 50) {
			document.body.style.color = '#fff'
		} else {
			document.body.style.color = '#000'
		}
	});
}

思维发散:

该接口适合的范围很窄,却能做出很贴心的用户体验。

1、当我们根据Ambient Light强度、陀螺仪信息、当地时间判断出用户正躺在床上准备入睡前在体验我们的产品,我们自然可以调整我们背景与文字颜色让用户感觉到舒适,我们还可以来一段安静的音乐,甚至使用Web Speech API播报当前时间,并说一声“晚安”,何其温馨;

2、该接口也可以应用于H5游戏场景,比如日落时分,我们可以在游戏中使用安静祥和的游戏场景;

3、当用户在工作时间将手机放在暗处,偷偷地瞄一眼股市行情的时候,我们可以用语音大声播报,“亲爱的,不用担心,你的股票中国中车马上就要跌停了”,多美的画面。

参考文献:
https://developer.mozilla.org/en-US/docs/Web/API
http://webaudiodemos.appspot.com/
http://www.w3.org/2009/dap/

转自 万技师 10 年前
3,872

原文:http://mathewsanders.com/designing-adaptive-layouts-for-iphone-6-plus/
翻译:叮当当咚当当小胖妞呀

从IOS6开始,苹果公司就一直建议我们使用自适应布局,但是迄今为止,我发现大家都在回避这个问题,考虑的最多的仍然是固定布局。

iPhone 6的上市让人们很难再去逃避自适应布局这个问题,四种屏幕尺寸(如果要支持iPad就要上升到5种)、三种分辨率和转向似乎让着手于自适应布局变得更加简单。

在文章的最后,你应该能流畅使用 storyboards、 约束(constraints)和 size class特性,这三个是Apple为开发和制作自适应布局提供的Xcode工具。

所以下载Xcode6,给自己来杯饮料,留上一个小时的时间,让我们开始吧!

  • Storyboards
    • 模拟尺寸
  • 约束
    • 头部和尾部空间
    • 横向空间约束
    • 同等宽度约束
    • 纵横比约束
    • 约束管理
      • 添加约束
      • 检查和编辑现有约束
      • 删除约束
    • 布局问题和冲突
      • 错位视图警告
      • 约束缺失错误
  • Size Classes
    • 宽度和高度特性
    • 我们的目标…
    • 为通用的size class添加约束
    • 为iPhone纵向布局添加约束
    • 为iPhone横向布局添加约束
    • 编辑助手:设备预览
    • 为iPad布局添加约束
  • 使用布局和间隔视图
    • 布局视图样例
    • 间隔视图样例
  • 下一步

Storyboards

Xcode中,storyboards可以让你在屏幕上拖动和放置原生对象(例如按钮、图片、文本框和标签)并且定义每个屏幕之间如何连接。

在Xcode专业术语中,可以看到、摸到、互动的用户界面元素,我们称之为 视图(按钮、图片、文本框、标签等等)。

包含并管理所有那些视图的屏幕被称为 视图控制器,我倾向于交替使用这些术语。

当我们在一个storyboard上添加视图控制器的时候,它的纵横比其实跟任何设备都不匹配,事实上,它是一个完美的600pt*600pt的正方形:

这提醒了我们,storyboard屏幕并不代表特定硬件上的屏幕,而是 任何IOS设备的抽象表现。

模拟尺寸

也许你不介意在600pt*600pt的画布上操作,但是在实际大小上操作可能会更有帮助。

我们可以非常方便的在Xcode里改变视图控制器模拟的尺寸和转向:

约束

向你们展示约束的最好方法是实例。

我们先创建一个简单的包含一个屏幕的storyboard(模拟4英寸iPhone的尺寸),再添加两个相邻的正方形。

当我们在竖屏中运行app的时候,这两个正方形完全按照我们的布局排列,当我们变成横屏时,它们仍然忠于自己的坐标:

当我们使用iPhone 6模拟器运行项目的时候,我们可以再一次看到,我们的布局并没有自适应不同的屏幕尺寸,屏幕右边多出了可见的空白区域。

这是由于没有约束,这些对象仍然会按照我们在storyboard上创建的x,y坐标和面积来定位。

所以让我们开始添加约束,看看会对它们有些什么影响。

头部和尾部空间

我们在蓝色方块前添加10pt的头部空间约束,在红色方块后添加10pt的尾部空间约束。

当我们运行项目的时候,约束把蓝色方块固定在屏幕左侧,把红色方块固定在右侧。

横向空间约束

我们在两个方块之间再添加一个10pt的横向空间约束,就像上一个约束一样,这样会让两个方块之间有一个固定的空间。

当我们运行项目的时候,会发现一个意料之外的结果:我们所有的约束都满足了,但是为了满足所有约束,其中一个方块被拉伸了。

这似乎告诉我们这样一件事:除非被告知,否则IOS会尽量让大多数对象都保持“自然”大小。

同等宽度约束

我们添加一个同等宽度约束。

当运行项目的时候,我们可以看到两个方块宽度的增量相同。

纵横比约束

最后,对两个方块添加纵横比约束。

这个约束保证了宽度和高度的比永远是相同的。

当我们运行app的时候,我们可以看到每个方块的宽度在增加,高度也同时在增加。

用iPhone 6模拟器运行项目,覆盖我们之前添加过的约束,你可以看到这两个正方形是如何利用可用空间来拉伸的。

约束管理

现在你已经看到了我们是如何使用约束的,下面我们来介绍一下具体操作。

提示:尽量少使用约束

添加约束的一个要点是试着挑战自己,越少使用约束越好。

虽然我并不认为添加的约束数量能够很大程度上影响IOS的性能,但是越少的使用约束,你的布局就会越好维护。

添加约束

在storyboard中添加约束有三个方法:

  1. 约束弹窗也许最好的方法就是选择一个或多个对象,从其中一个弹窗中添加约束。我认为这是个很好的方法,因为可以看到现有约束的范围。如果有一条约束不可用,可能就意味着你需要两个或更多对象来实施这条约束。
  2. ctrl + 拖动你可以按住ctrl键,同时拖动到一个对象上(可以是相邻对象、父级对象或者是自身),会出现一个浮层告诉你可以被添加的约束有哪些。这是我最喜欢的添加约束的方法,因为你不需要把你的鼠标移动到大老远的底部再回到对象。
  3. 菜单/绑定你也可以选择一个或多个对象,在菜单中点击 editor -> pin来选择约束,这其实是最没有效率的方法,但是如果你发现自己不停的重复添加一种约束,也许为一个或多个选项添加绑定更合理一点。

检查和编辑现有约束

检查视图中应用的约束最简单的办法就是选择视图,切换到Size检查面板。

或者在文档大纲层次面板中切换constant数值。

无论是哪种方法,选择约束可以让你直接更新它。

删除约束

同样的,约束也可以通过高亮+点击删除按钮来删除。

要删除一个视图的所有约束,或者屏幕中的所有约束,在布局问题弹窗中有一条捷径:

布局问题和冲突

当我们在storyboard中添加约束的时候,Xcode总会给出一些关于这些约束的警告或者错误。

有时候这些问题可以忽略不计,但是更多的时候,它们必须被解决。

查看约束警告和错误最好在文档大纲面板中,每个视图控制器会有一个红色或者黄色的icon来表示是不是有布局问题:

错位视图警告

一个比较常见的警告是错位视图警告,如果约束规定这个视图应该在的地方,和这个视图实际在的地方不匹配,那么这种警告随时会出现。

当你转换模拟尺寸或者不小心用鼠标移动了一个视图,这些警告也会出现。

点击一个错位的视图,屏幕上会出现一个虚线框,告诉你约束规定了这个视图应该在的位置。

如果点击警告,会出现一个带有几个选项的浮层,你可以选择让Xcode更新约束来匹配storyboard上的位置,也可以让Xcode更新框架来移动或者拉伸视图,使它们回到约束规定的位置。

缺失约束错误

让我们回到一开始蓝方块和红方块的例子,我们没有添加过一个关于纵向位置的约束,但当我们运行app的时候看起来完全没问题,因为IOS会认为纵向位置就是我们在storyboard上放置的位置,不过为了避免一些意料之外的行为,我们最好还是规定一下。

在 顶部布局向导添加顶部空间约束可以消除一些说不定道不明的约束和错误。

Size Classes

为了在大多数基础布局或者更高级的布局上使用约束,你需要同时使用size classes。

Size classes是一种能够告诉你物理设备宽度和高度的特性。

当我们在storyboard的屏幕上添加对象或者约束时,只有设备符合当前的宽高特性,对象才会显现,约束才会被应用。

这是一个非常有用的方法,它让我们确定了不同设备和转向下布局的变化。

高度和宽度特性

使用 紧凑(compact)、 任意(any)和 正常(regular)这三种的组合,可以让我们确定一些范围内的设备布局。

虽然不能涉及每一个变化(比如不能确定iPhone 6 Plus的竖向模式,也不能让iPad的转向消失),但是大多数的变化都可以确定。

我们说过,介绍size classes最简单的方法是实例,所以让我们看一个例子。

我们的目标…

作为例子,我们做一个Instagram详情页的简单版本,可以适应大屏和转向。

我们的目标是创建一个布局,它可以机智的适应更大的iPhone 6设备(我说的机智,是指只有照片会放大,其他的元素如头像照片仍然不变),并且当设备横屏的时候,图片和元数据会并肩排列,而不是像竖屏时的上下排列。

为通用的size class添加约束

跟之前的例子不同,这次我们不使用模拟尺寸度量,我们使用通用size class的抽象方形布局,这样会使我们记住,为这个size class添加的任何视图和约束,只能是那些添加在任意屏幕尺寸和转向上的视图和约束。

我们需要用到这些约束:

除了必要的空间、间隙和纵横比约束,我们还需要让某些对象排列在顶部或者底部。

现在,在你的storyboard上添加视图和约束吧。做这步的时候,我的storyboard长这样:

注意,现在我们有了所有转向上所需要的元素,但是我没有费心完成每个转向上的布局,下一步我们才会做!

为iPhone纵向布局添加约束

现在,我们把size class切换到 紧凑宽度和 正常高度,这个尺寸特性的组合适用于任何竖屏下的iPhone设备。

如果要切换size classes,点击storyboard中下方的size class标签,选择你想要看到的宽高组合。

注意,当你切换size class时,视图控制器的尺寸会更新来显示新的抽象布局。

最后,你可以重新定位、拉伸视图和添加竖屏上的约束了。这里有一些我添加到竖向布局上的约束:

这是我做到这步时,我的storyboard的样子:

在这个阶段,你可以用任何的iPhone模拟器(3.5、4、4.7或者5.5英寸屏幕)来运行你的项目,看看竖屏情况下的布局是否合理,虽然如果转向成横屏时,布局看上去会一团糟。

注意,我们没有固定图片的宽度,我们只是简单地把图片的左右边缘固定在屏幕两侧。当变为更大的iPhone 6屏幕尺寸时,图片会被拉伸,又因为我们添加了一个固定图片纵横比的约束,所以高度也会同时增加。

为iPhone横向布局添加约束

现在切换size class到 任意宽度和 紧凑高度,这种尺寸特性的组合适用于任何横屏下的iPhone设备,并且会为了满足横屏视图下的目标更新布局。

这次,图片的顶部、左边和底部边缘都被固定在父级视图的边缘。

这个局部另一个有意思的地方是,在评论标签上添加的尾部空间约束。

当图片的约束使得图片变大的时候,这个标签上的约束会使得自身变窄。为了适应这种视图下的文本,文本高度需要增加到两行——的确如此!

下图是我做到这步时storyboard的样子。注意,在文档大纲中,一些约束会稍稍渐隐,这些约束是在竖向视图中我们添加的,它们仍然存在,但是当我们选中当前的宽高特性时,它们不会被应用。

也要注意,当你转换宽高特性时,storyboard会更新以便显示你为那些特性增加的约束。太棒了!

现在运行项目,我们会发现当转向改变时,我们有了一个既适用于横屏又适用于竖屏的布局,更棒的是在转向时,会有一个完美的过渡动画。

我把整个过渡动画放慢,这样你们能看的更加清楚。注意动画中也有层级关系,正由于此,即使在正常布局下视图并没有重叠,我们也需要考虑如何安排视图的层级关系……

编辑助手:设备预览

Xcode另外一个很有用的东西:设备预览助手。你不再需要无数次运行项目来检查你的布局是否正确,你只需要使用编辑助手storyboard预览,选择你想要的所有设备和转向就可以了。

这并不是完美的(比如导航条的颜色在这个例子中缺失了),但是它却是一个很好地选择,它可以让你把你自己的语言切换到双倍长度伪语言,可以在你的storyboard中重复任何文本。

这是我storyboard上的预览助手,它展示了一个3.5英寸横屏和4英寸竖屏的iPhone,你可以看到我还需要再加工加工来适应更长的标签……-_-

为iPad布局添加约束

现在,切换size classes到 正常宽度和 正常高度,这是iPad横屏和竖屏的特性。

就像之前一样,我们重新定位、拉伸我们的视图。对于iPad布局,我决定使用固定尺寸的图片(所以它不会像在iPhone上那样切换横竖屏时会改变大小),元数据都显示在图片底部。

下图是我在重新排列视图并添加了约束之后的storyboard:

到现在为止,我们为某些特别的size class特性添加了约束,但是现在我们要尝试些不同的东西。

由于iPad上会有多余的空间,我们不要仅仅只是重排视图,让我们来加一点额外的内容。对于这个例子来说,我们再加两张图片(也许是在这张主照片之前和之后拍摄的照片)。

这是我的storyboard更新之后的样子:

我原本可以手动输入这些次级图片的宽高,但我没有,取而代之的是我让它们的尺寸变成主图片的某个比例。

这样做的好处是如果我们决定改变主图片的尺寸,布局的其他部分会自动的计算并且更新次级图片的宽高,而不用我们手动输入。

这是一张我截的图,我改变了主图片的宽度约束,可以看到其他的部分也随之更新了。

我没有在iPad模拟器上运行项目并截屏,不过这里有一些横屏和竖屏的效果图:

使用布局和间隔视图

Xcode中有些约束我们可以随时运用,但是对于一些些常见的布局,我们需要一点帮助。

布局视图样例

要把一个视图的边缘固定在父级视图的边缘,或者把它固定在父级视图的正中心是件很简单的事情,~~但是我没有发现简便的方法,让视图固定在离正中心有一段固定距离的地方。~~感谢Jeff Nouwen指出,在把视图固定在中间后,你可以改变constant值来达到你的期望。

理论上来说,我们需要的是一个‘ 中心排列导向’,即任何视图都能水平和垂直居中与父级视图中:

为了实现这个目标,通过现在我们可以使用的约束,我们把我们的视图嵌入一个外层视图(这个外层视图没有背景色,只是为了帮助我们布局而存在),可以把它定位在父级视图的中间。

通过这个方法,你的约束看起来可能像这样:

现在我比较喜欢让我的布局层级尽量平。另外一个不使用外层视图的方法,我叫它 布局视图

使用这种方法,我倾向于在storyboard中添加一个颜色明亮的视图,然后把它的hidden属性设置为true,你仍然可以在storyboard布局中看到它(虽然稍稍渐隐),但是运行模拟器的时候它不会出现。

现在你在你的视图和布局视图中可以添加 居中排列(align center to center)

间隔视图样例

之前我们看到了我们是如何固定视图边缘到父级视图边缘的间隙,使得当父级视图变大时,间隙约束也会让视图变大。

但是如果我们想要视图仍然保持原来的大小,在父级视图变大时,视图之间的间隙也变大呢?

理论上来说,我们想要某种类似 同等宽度约束的约束,只不过同等宽度约束是作用在视图上,我们想让它作用在约束上。

此时我们需要添加 间隔视图来帮助我们布局,但由于我们不想在运行app时看到它们,我们会把它们的hidden属性设置为true

使用这项技术的方法,是为每一个你想要等比增长的间隙添加一个间隔视图,把其他视图的边缘固定在间隔视图的边缘上,然后为所有的间隔视图添加 同等宽度约束

下一步

现在希望你们已经完全有信心开始探索应用约束的布局了。

不要指望能即刻成功,Xcode是一个非常复杂的工具,除了storyboard和约束之外它还有很多其他功能,有些功能刚开始使用会觉得很神秘和困惑。就像其他复杂的工具一样,在你熟悉它的怪癖之前你还需要一段适应时间,但是我建议你尽早的去熟悉它,因为我预计(至少我希望)下一代设计师会更多地使用Xcode这样的工具而非Photoshop。

如果你是一位创建设计规范的设计师,并想让IOS开发者遵循你的规范,你应该开始考虑和你的设计团队沟通的最好方法。也许你会创建一个视觉语言来描述你想要应用的约束。

我个人认为,设计师应该更多地承担一些他们创建工作上的责任,而不是让一个前端开发人员重新创建设计意图,而设计师只是管理storyboard文件。

如果你发现这个教程上有任何难以理解的地方,或者有错误的敌方,请让我知道,我会尽快更新这篇文章。

转自 携程设计委员会 10 年前
4,992

使网页变灰色,只需要一句 css 代码:

html { filter: grayscale(1); }

在 I10 / IE11 上的兼容方案需要 grayscale.js,参考此文:http://www.cnblogs.com/wangmeijian/p/4324693.html

CSS 背景图片变灰:https://stackoverflow.com/questions/16340159/greyscale-background-css-images


xoyozo 15 年前
6,206

PNG半透明背景图片效果
PNG图片在网页设计中扮演着一个很重要的角色,利用PNG图片的特点可以制作出实用,绚丽的效果,可是对于PNG图片的支持却不是很理想,Firefox和Opera对PNG支持的比较好,特别是Firefox浏览器。可是IE却不理PNG,使得设计者无法很随意的使用png图片。

IE5.5+的AlphaImageLoader滤镜为通向png提供了一个道路,如果他载入的是PNG(Portable Network Graphics)格式,则0%-100%的透明度也被提供。我们就利用这个滤镜和hack来设计一个半透明png背景图片的模型

这里是个超链接测试

(X)HTML: <div id="wrap">
<p><a href="http://www.jluvip.com"><strong>PNG半透明背景图片效果</strong></a><br />:PNG图片在网页设计中扮演着一个很重要的角色,利用PNG图片的特点可以制作出需要使用绚丽的效果,可是对于PNG图片的支持却不是很理想,Firefox和Opera对PNG支持的比较好,特别是Firefox浏览器。可是IE却不理PNG,是的设计者无法很随意的使用png图片。</p>
<p>IE5.5+的AlphaImageLoader滤镜为通向png提供了一个道路,如果他载入的是PNG(Portable Network Graphics)格式,则0%-100%的透明度也被提供。我们就利用这个滤镜和hack来设计一个半透明png背景图片的模型
</p>
<p><a class="test" href="http://www.jluvip.com">这里是个超链接测试</a></p>
CSS: #wrap{ width:460px;margin:20px auto 20px 80px;text-align:left;height:300px; padding:20px; border:1px #eee solid;}
/*not for ie 6.0*/
html>body #wrap{background: url(img/bgcanvas.png) repeat;}
/*for ie 6.0*/
* html #wrap {
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src="img/bgcanvas.png");
background:none;
}
#wrap a{color:#c00; text-decoration: none; position:relative;}/*解决IE下链接失效的问题*/
#wrap a:hover{ text-decoration:underline;}

nbsp;

观看效果

3,741
string chkCode = string.Empty;
//颜色列表,用于验证码、噪线、噪点
//Color[] color ={Color.White, Color.Yellow, Color.LightBlue, Color.LightGreen,
//                Color.Orange, Color.LightCyan, Color.LightPink, 
//                Color.LightSalmon };
Color[] color = {Color.Black, Color.Blue, Color.Red, Color.DarkViolet, 
                 Color.Chocolate, Color.DarkGreen, Color.DeepSkyBlue, 
                 Color.DarkCyan };
//字体列表,用于验证码 
string[] font = {"Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh",
                 "PMingLiU", "Impact" };
//验证码的字符集,去掉了一些容易混淆的字符 
char[] character ={'2', '3', '4', '5', '6', '8', '9', 'A', 'B', 'C', 'D', 'E',
                   'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T',
                   'W', 'X', 'Y' };
Random rnd = new Random();
//生成验证码字符串 
for (int i = 0; i < 4; i++)
{
    chkCode += character[rnd.Next(character.Length)];
}
//把验证码存入session
Session["chkCode"] = chkCode;
Bitmap bmp = new Bitmap(65, 20);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.Transparent);//背景色
//画噪线 
for (int i = 0; i < 0; i++)
{
    int x1 = rnd.Next(65);
    int y1 = rnd.Next(20);
    int x2 = rnd.Next(65);
    int y2 = rnd.Next(20);
    Color clr = color[rnd.Next(color.Length)];
    g.DrawLine(new Pen(clr), x1, y1, x2, y2);
}
//画验证码字符串
for (int i = 0; i < chkCode.Length; i++)
{
    string fnt = font[rnd.Next(font.Length)];
    Font ft = new Font(fnt, 15);
    Color clr = color[rnd.Next(color.Length)];
    g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr),
        (float)i * 15 + 2, (float)0);
}
//画噪点 
for (int i = 0; i < 50; i++)
{
    int x = rnd.Next(bmp.Width);
    int y = rnd.Next(bmp.Height);
    Color clr = color[rnd.Next(color.Length)];
    bmp.SetPixel(x, y, clr);
}
//清除该页输出缓存,设置该页无缓存 
Response.Buffer = true;
Response.ExpiresAbsolute = System.DateTime.Now.AddMilliseconds(0);
Response.Expires = 0;
Response.CacheControl = "no-cache";
Response.AppendHeader("Pragma", "No-Cache");
//将验证码图片写入内存流,并将其以 "image/Png" 格式输出 
MemoryStream ms = new MemoryStream();
try
{
    bmp.Save(ms, ImageFormat.Png);
    Response.ClearContent();
    Response.ContentType = "image/Png";
    Response.BinaryWrite(ms.ToArray());
}
finally
{
    //显式释放资源 
    bmp.Dispose();
    g.Dispose();
}
xoyozo 17 年前
4,919

研究了两个小时,确认了一个BUG。

平台:VS2005,VS2008 (VS2003未知)

Framework:2.0,3.5 (1.1未知)

首先跟我做一遍,非常简单:

一、在 VS 中新建网站;
二、已有 Default.aspx,再建 Default2.aspx;
三、在这两个网页的 Page_Load 事件上分别加上断点
四、在 Default2.aspx 中拖入一个 ImageButton,并设该页为起始页
五、运行。

这时可以发现,程序在两处断点的地方都会停下来,而这两上网页根本就没有任何关系,只是在同一级目录而已。

经测试,ImageMap 控件也有同样的现象,其它的就没一一去试了。

建议大家尽量用Button代替ImageButton。按照下面的做法可以把Button美化成和ImageButton一样的效果,甚至更棒!

方法如下:

给 Button 加上 CssClass 属性来写样式,或在App_Themes 的 .skin 文件中定义 Button 的属性

<asp:Button runat="server" CssClass="ButtonStyle" />

 

然后在 .css 文件中处理它的样式,例如:

 

.ButtonStyle {
border:0;
color: #FFFFFF;
font-size: 14px;
font-weight:bold;
text-align: center;
vertical-align:middle;
line-height:27px;
height: 27px;
width: 77px;
background-color: transparent;
background-image: url(Images/button.gif);/*背景*/
background-position: center center;
}

 

这样就可以了,这时你会发现写在 Button 上的 Text 会随着你的鼠标按下而偏移,这个效果是不是 ImageButton 所没有的呢?

xoyozo 17 年前
5,175