移动端 Retina屏 各大主流网站1px的解决方案

Retina屏的移动设备如何实现真正1px的线?

在retina屏下面,如果你写了这样的meta <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
你将永远无法写出1px宽度的东西,除此之外,inline的SVG等元素,也会按照逻辑像素来渲染,整个页面的清晰度会打折;

先看看  “诸子百家 ”  是如何实现的;

先看看百度糯米的

@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2) {
.normal-goods .good-content {
border: none;
background-image: -webkit-linear-gradient(90deg,#e0e0e0,#e0e0e0 50%,transparent 50%);
background-image: -moz-linear-gradient(90deg,#e0e0e0,#e0e0e0 50%,transparent 50%);
background-image: -o-linear-gradient(90deg,#e0e0e0,#e0e0e0 50%,transparent 50%);
background-image: linear-gradient(0,#e0e0e0,#e0e0e0 50%,transparent 50%);
background-size: 100% 1px;
background-repeat: no-repeat;
background-position: bottom
}
}

  

再看看  大众点评的

.index-rec .home-tuan-list .cnt {
    padding: 7px 10px 10px 0;
    display: box;
    display: -webkit-box;
    display: -ms-flexbox;
    height: 78px;
    background-image: url(//www.dpfile.com/mod/app-m-style/1.7.2/css/img/repeat-x.png);
    background-repeat: repeat-x;
    background-position: 0 bottom;
    background-size: auto 1px
}

再看再看看 阿里去啊 ,其中 hairlines挂到  <html class=‘hairlines‘上>

<script>
	if (/iP(hone|od|ad)/.test(navigator.userAgent)) {  //  就是放到html根节点上的   ios8现在普及率高了,可以省略
		var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/), version = parseInt(
				v[1], 10);
		if (version >= 8) {
			document.documentElement.classList.add(‘hairlines‘)
		}
	};
</script>

  

.r1bt {
    border-top: 1px solid rgba(32,35,37,.15)
}

.r1bb {
    border-bottom: 1px solid rgba(32,35,37,.15)
}

.r1bl {
    border-left: 1px solid rgba(32,35,37,.15)
}

.r1br {
    border-right: 1px solid rgba(32,35,37,.15)
}

.r1b {
    border: 1px solid rgba(32,35,37,.15)
}

.hairlines .r1bt,.hairlines .r1bb,.hairlines .r1bl,.hairlines .r1br,.hairlines .r1b {
    border-width: .5px!important
}

早期阿里去啊不是这样的 ,是这样写的,兼容性非常好

/*retain 1px border start*/
.retainbt,.retainbb,.retainbl,.retainbr,.retainb { position: relative;position: relative !important}
.retainbt:before,.retainbb:after {pointer-events: none;position: absolute;content: ""; height: 1px; background: rgba(32,35,37,.24);left: 0;right: 0}
.retainbt:before {top: 0}
.retainbb:after {bottom: 0}
.retainbl:before,.retainbr:after {pointer-events: none;position: absolute;content: ""; width: 1px; background: rgba(32,35,37,.24); top: 0; bottom: 0}
.retainbl:before {left: 0}
.retainbr:after {right: 0}
.retainb:after {position: absolute;content: "";top: 0;left: 0; -webkit-box-sizing: border-box; box-sizing: border-box; width: 100%; height: 100%; border: 1px solid rgba(32,35,37,.24); pointer-events: none}

@media (-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution: 144dpi),(min-resolution:1.5dppx) {
.retainbt:before,.retainbb:after {-webkit-transform:scaleY(.5);transform: scaleY(.5) }
.retainbl:before,.retainbr:after {-webkit-transform: scaleX(.5); transform: scaleX(.5) }
.retainb:after { width: 200%; height: 200%;-webkit-transform: scale(.5); transform: scale(.5) }
.retainbt:before,.retainbl:before,.retainb:after {-webkit-transform-origin: 0 0;transform-origin: 0 0}
.retainbb:after,.retainbr:after { -webkit-transform-origin: 100% 100%;transform-origin: 100% 100%}
}

@media (-webkit-device-pixel-ratio:1.5) {
.retainbt:before,.retainbb:after { -webkit-transform: scaleY(.6666); transform: scaleY(.6666) }
.retainbl:before,.retainbr:after {-webkit-transform: scaleX(.6666); transform: scaleX(.6666)}
.retainb:after {width: 150%; height: 150%;-webkit-transform: scale(.6666); transform: scale(.6666) }
}

@media (-webkit-device-pixel-ratio:3) {
.retainbt:before,.retainbb:after { -webkit-transform: scaleY(.3333); transform: scaleY(.3333)}
.retainbl:before,.retainbr:after { -webkit-transform: scaleX(.3333); transform: scaleX(.3333)}
.retainb:after {width: 300%;height: 300%; -webkit-transform: scale(.3333);transform: scale(.3333)}
}

 然后 再看看rem的解决方案

美团的

<script type="text/javascript">
        //根据屏幕大小及dpi调整缩放和大小
        (function() {
            var scale = 1.0;
            var ratio = 1;
            if (window.devicePixelRatio >= 2) {
                scale *= 0.5;
                ratio *= 2;
            }
            var text = ‘<meta name="viewport" content="initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale +‘, minimum-scale=‘ + scale + ‘, width=device-width, user-scalable=no" />‘;
            document.write(text);
            document.documentElement.style.fontSize = 50*ratio + "px";
        })();
    </script>

  我们把美团的 改变一下也可以

美团的 改变一下
 <meta name="viewport" content="target-densitydpi=device-dpi">  <!--安卓自带的 device-width 先不加 否则iphone 随进线条出现问题 -->
<script>
+function(win,doc,undefined) {//根据屏幕大小及dpi调整缩放和大小
	var scale = 1.0,ratio = 1,dc=doc,viewporttexts=‘‘;
	if (win.devicePixelRatio && devicePixelRatio >= 1.5) {
		ratio = devicePixelRatio;
		scale = scale/(devicePixelRatio);
	}
	//var texts = ‘<meta  name="viewport" content="initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale +‘, minimum-scale=‘ + scale + ‘, width=device-width, user-scalable=no" />‘;
	// dc.write(texts);
	  viewporttexts = ‘ width=device-width, initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale +‘, minimum-scale=‘ + scale + ‘,user-scalable=no‘;
      doc.querySelector(‘meta[name="viewport"]‘).setAttribute("content",viewporttexts);

	   console.log(‘111‘);
      dc.documentElement.style.fontSize =doc.getElementsByTagName("html")[0].style.fontSize=Math.ceil(50*ratio) + "px";
}(window,document);
 </script>

   最后淘宝的 这段代码有点旧了    https://github.com/amfe/lib-flexible

<script>
!function(N, M) {
    function L() {
        var a = I.getBoundingClientRect().width;
        a / F > 540 && (a = 540 * F);
        var d = a / 10;
        I.style.fontSize = d + "px",
        D.rem = N.rem = d
    }
    var K, J = N.document, I = J.documentElement, H = J.querySelector(‘meta[name="viewport"]‘), G = J.querySelector(‘meta[name="flexible"]‘), F = 0, E = 0, D = M.flexible || (M.flexible = {});
    if (H) {
        console.warn("将根据已有的meta标签来设置缩放比例");
        var C = H.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
        C && (E = parseFloat(C[1]),
        F = parseInt(1 / E))
    } else {
        if (G) {
            var B = G.getAttribute("content");
            if (B) {
                var A = B.match(/initial\-dpr=([\d\.]+)/)
                  , z = B.match(/maximum\-dpr=([\d\.]+)/);
                A && (F = parseFloat(A[1]),
                E = parseFloat((1 / F).toFixed(2))),
                z && (F = parseFloat(z[1]),
                E = parseFloat((1 / F).toFixed(2)))
            }
        }
    }
    if (!F && !E) {
        var y = N.navigator.userAgent
          , x = (!!y.match(/android/gi),
        !!y.match(/iphone/gi))
          , w = x && !!y.match(/OS 9_3/)
          , v = N.devicePixelRatio;
        F = x && !w ? v >= 3 && (!F || F >= 3) ? 3 : v >= 2 && (!F || F >= 2) ? 2 : 1 : 1,
        E = 1 / F
    }
    if (I.setAttribute("data-dpr", F),
    !H) {
        if (H = J.createElement("meta"),
        H.setAttribute("name", "viewport"),
        H.setAttribute("content", "initial-scale=" + E + ", maximum-scale=" + E + ", minimum-scale=" + E + ", user-scalable=no"),
        I.firstElementChild) {
            I.firstElementChild.appendChild(H)
        } else {
            var u = J.createElement("div");
            u.appendChild(H),
            J.write(u.innerHTML)
        }
    }
    N.addEventListener("resize", function() {
        clearTimeout(K),
        K = setTimeout(L, 300)
    }, !1),
    N.addEventListener("pageshow", function(b) {
        b.persisted && (clearTimeout(K),
        K = setTimeout(L, 300))
    }, !1),
    "complete" === J.readyState ? J.body.style.fontSize = 12 * F + "px" : J.addEventListener("DOMContentLoaded", function() {
        J.body.style.fontSize = 12 * F + "px"
    }, !1),
    L(),
    D.dpr = N.dpr = F,
    D.refreshRem = L,
    D.rem2px = function(d) {
        var c = parseFloat(d) * this.rem;
        return "string" == typeof d && d.match(/rem$/) && (c += "px"),
        c
    }
    ,
    D.px2rem = function(d) {
        var c = parseFloat(d) / this.rem;
        return "string" == typeof d && d.match(/px$/) && (c += "rem"),
        c
    }
}(window, window.lib || (window.lib = {}));
</script>

用rem写1px 维护行方便;   

缺点:但是  动态控制  viewport  retain下,无论美团还是淘宝用 rem始终还有许多细小的问题;在ios上浏览器打开仔细看还是看的出的,安卓上没看出来;

有时候retain下, viewport  缩放动态控制字体大小;<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">  竖线或者奇数偶数行横线   视窗控制之后的1px线条,有的1.1px  或者1.2px等等...拿手机仔细看下,观察iphone5 以及iphone6  下就知道,但是截图出来也看不出来问题的(只是示范一下),真机上细看还是明显的;

美团KTV 全城 默认排序 刷选的 分割线 ;iphone5s 刷选的那条是正常的鹅;前面3条1px多了点;ip6上则不是;

上面 有的 竖线始终 感觉 宽度是 不是1px;宽了一点点;首页美食类目进去;每个店铺边框  偶尔几条线条是1px多了一点点;

喜欢那种就用那种好了;

顺便附个H5  Canvas  Retina屏幕处理的1px的函数

/**
 * HiDPI Canvas Polyfill (1.0.9)
 *
 * Author: Jonathan D. Johnson (http://jondavidjohn.com)
 * Homepage: https://github.com/jondavidjohn/hidpi-canvas-polyfill
 * Issue Tracker: https://github.com/jondavidjohn/hidpi-canvas-polyfill/issues
 * License: Apache 2.0
*/
;(function(prototype) {

	var pixelRatio = (function(context) {
			var backingStore = context.backingStorePixelRatio ||
						context.webkitBackingStorePixelRatio ||
						context.mozBackingStorePixelRatio ||
						context.msBackingStorePixelRatio ||
						context.oBackingStorePixelRatio ||
						context.backingStorePixelRatio || 1;

			return (window.devicePixelRatio || 1) / backingStore;
		})(prototype),

		forEach = function(obj, func) {
			for (var p in obj) {
				if (obj.hasOwnProperty(p)) {
					func(obj[p], p);
				}
			}
		},

		ratioArgs = {
			‘fillRect‘: ‘all‘,
			‘clearRect‘: ‘all‘,
			‘strokeRect‘: ‘all‘,
			‘moveTo‘: ‘all‘,
			‘lineTo‘: ‘all‘,
			‘arc‘: [0,1,2],
			‘arcTo‘: ‘all‘,
			‘bezierCurveTo‘: ‘all‘,
			‘isPointinPath‘: ‘all‘,
			‘isPointinStroke‘: ‘all‘,
			‘quadraticCurveTo‘: ‘all‘,
			‘rect‘: ‘all‘,
			‘translate‘: ‘all‘,
			‘createRadialGradient‘: ‘all‘,
			‘createLinearGradient‘: ‘all‘
		};

	if (pixelRatio === 1) return;

	forEach(ratioArgs, function(value, key) {
		prototype[key] = (function(_super) {
			return function() {
				var i, len,
					args = Array.prototype.slice.call(arguments);

				if (value === ‘all‘) {
					args = args.map(function(a) {
						return a * pixelRatio;
					});
				}
				else if (Array.isArray(value)) {
					for (i = 0, len = value.length; i < len; i++) {
						args[value[i]] *= pixelRatio;
					}
				}

				return _super.apply(this, args);
			};
		})(prototype[key]);
	});

	 // Stroke lineWidth adjustment
	prototype.stroke = (function(_super) {
		return function() {
			this.lineWidth *= pixelRatio;
			_super.apply(this, arguments);
			this.lineWidth /= pixelRatio;
		};
	})(prototype.stroke);

	// Text
	//
	prototype.fillText = (function(_super) {
		return function() {
			var args = Array.prototype.slice.call(arguments);

			args[1] *= pixelRatio; // x
			args[2] *= pixelRatio; // y

			this.font = this.font.replace(
				/(\d+)(px|em|rem|pt)/g,
				function(w, m, u) {
					return (m * pixelRatio) + u;
				}
			);

			_super.apply(this, args);

			this.font = this.font.replace(
				/(\d+)(px|em|rem|pt)/g,
				function(w, m, u) {
					return (m / pixelRatio) + u;
				}
			);
		};
	})(prototype.fillText);

	prototype.strokeText = (function(_super) {
		return function() {
			var args = Array.prototype.slice.call(arguments);

			args[1] *= pixelRatio; // x
			args[2] *= pixelRatio; // y

			this.font = this.font.replace(
				/(\d+)(px|em|rem|pt)/g,
				function(w, m, u) {
					return (m * pixelRatio) + u;
				}
			);

			_super.apply(this, args);

			this.font = this.font.replace(
				/(\d+)(px|em|rem|pt)/g,
				function(w, m, u) {
					return (m / pixelRatio) + u;
				}
			);
		};
	})(prototype.strokeText);
})(CanvasRenderingContext2D.prototype);
;(function(prototype) {
	prototype.getContext = (function(_super) {
		return function(type) {
			var backingStore, ratio,
				context = _super.call(this, type);

			if (type === ‘2d‘) {

				backingStore = context.backingStorePixelRatio ||
							context.webkitBackingStorePixelRatio ||
							context.mozBackingStorePixelRatio ||
							context.msBackingStorePixelRatio ||
							context.oBackingStorePixelRatio ||
							context.backingStorePixelRatio || 1;

				ratio = (window.devicePixelRatio || 1) / backingStore;

				if (ratio > 1) {
					this.style.height = this.height + ‘px‘;
					this.style.width = this.width + ‘px‘;
					this.width *= ratio;
					this.height *= ratio;
				}
			}

			return context;
		};
	})(prototype.getContext);
})(HTMLCanvasElement.prototype);

  

时间: 2024-10-12 01:18:49

移动端 Retina屏 各大主流网站1px的解决方案的相关文章

移动端,多屏幕尺寸高清屏retina屏适配的解决方案

移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点: 首先,选取一款手机的屏幕宽高作为基准(以前是iphone4的320×480,现在更多的是iphone6的375×667). 对于retina屏幕(如: dpr=2),为了达到高清效果,视觉稿的画布大小会是基准的2倍,也就是说像素点个数是原来的4倍(对i

7种方法解决移动端Retina屏幕1px边框问题

在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样.没有办法,只有在后面的版本中去修改了,但是要改的话,需要知道是为什么.所以查了很多资料,终于搞懂了这个问题,并且总结了几种方法. 造成边框变粗的原因 其实这个原因很简单,因为css中的1px并不等于移动设备的1px,这些由于不同的手机有不同的像素密度.在window对象中有一个devicePixe

学习游戏要学习编程语言吗?十大主流编程语言解析

计算机的发展,促使了一个新的职业的出现,程序员是近些年出现的并且得到了广泛关注的一个职业,相信这也是很多莘莘学子的职业梦想.但程序员也有很多种,并不是每一个程序员能够精通所有的编程语言.所谓术业有专攻,如果将来志在编程世界的网友就要注意了,今天给大家推荐一下2014年最流行的编程语言,他们可以说是未来程序员们生存的工具. 1.JavaScript JavaScript在Web应用上有着非常大的需求,JavaScript主要用于实现为Web浏览器,以提供增强的用户界面和动态网站. 直到google

移动端多屏适配方案

原文:http://www.cocoachina.com/webapp/20150715/12585.html?utm_source=tuicool 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点: 1)首先,选取一款手机的屏幕宽高作为基准(以前是iPhone4的320×480,现在更多的是iphone6的375×667).

html5开发移动端app的7大优势(一)

移动web端APP是如今市场份额占据霸主,自html5开发语言正式封稿后,使用html5语言开发app应用带来的用户体验和制作难度是其他语言远远不如的.本文华清创客学院为读者解析html5开发移动端app的7大优势.让对html5感兴趣的读者更好的了解html5网页开发技术. html5开发移动端app的7大优势(一): 1.跨平台: 开发者的幸福指数随着多屏时代的来临岌岌可危.人人都期盼HTML5能扮演救星.多套代码.不同技术工种.业务逻辑同步,这是折磨人的过程.有点类似个人电脑早期世界,那个

现在主流网站为什么都用div+css布局而不是用table

由于刚刚接触前端,一直觉得table布局在代码上看起来比div+css更整洁,div+css布局的页面,一堆的<div><div><div>...</div></div></div>看起来都让人犯密集恐惧症,那么为什么现在的主流网站还都乐此不疲呢?为什么div+css反而成了一种主流布局方式呢?一直对此不解.这篇文章好像是解决了我的问题,先摘录过来,以便查阅. 以下内容摘自:http://www.divcss5.com/wenji/w

Android中级篇之百度地图SDK v3.5.0-一步一步带你仿各大主流APP地图定位移动选址功能

定位+移动选址 百学须先立志-学前须知: 我们经常在各大主流APP上要求被写上地址,如百度外卖.爱鲜蜂收货地址等等:其中他们大多数是可以让我们在地图上移动选址.就如下面这段GIF演示的一样: 尽信书,不如无书-能学到什么? 1.地图状态MapStatus类及监听setOnMapStatusChangeListener 2.定位LocationClient类 3.反地理编码GeoCoder类 工欲善其事必先利其器-申请Key 百度地图访问应用(AK)申请地址:http://lbsyun.baidu

XSuperMES移动端运用FragmentActivity适配大屏幕(一)

XSuperMES移动端运用FragmentActivity适配大屏幕 XSuperMES移动端运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视.针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套app,然后拷贝一份,修改布局以适应什么超级大屏的.难道无法做到一个app可以同时适应手机和平板吗?答案是,当然有,那就是Fragment.Fragment出现的初衷就是为了解决这样的问题. 你可以把Fragment当成Activity一个界面的一部分,甚至Activity的界面由完全不

主流网站开发语言

主流网站开发语言之ASP:ASP是微软(Microsoft)所开发的一种后台脚本语言,它的语法和Visual BASIC类似,可以像SSI(Server Side Include)那样把后台脚本代码内嵌到HTML页面中.虽然ASP简单易用,但是它自身存在着许多缺陷,最重要的就是安全性问题.目前在微软的 .net 战略中新推出的ASP.net 借鉴了Java技术的优点,使用C Sharp (C#) 语言作为ASP.net的推荐语言,同时改进了以前ASP的安全性差等缺点.但是,使用ASP/ASP.n