1.CSS移动端1px(线条/边框)解决方案
2.BigDecimal转换成String的码分精度问题
3.caffe ä¸ä¸ºä»ä¹bnå±è¦åscaleå±ä¸èµ·ä½¿ç¨
4.Kubernetes —— Pod 自动水平伸缩源码剖析(上)
5.大屏适配的几种方式
6.android Matrix.setRotate å postRotateçåºå«
CSS移动端1px(线条/边框)解决方案
由于不同的手机有不同的像素密度导致的。如果移动显示屏的码分分辨率始终是普通屏幕的2倍,1px的码分边框在devicePixelRatio=2的移动显示屏下会显示成2px,所以在高清瓶下看着1px总是码分感觉变胖了小编阅读过其他作者的文章中有写0.5px的写法,在理论上最小的码分单位是1px。所以会出现有的码分ssm 管理系统源码设备写0.5px无效(没有边框)的情况。
如何使用正确的码分1px单位又能在移动设备上显示1px的效果呢?
本文将介绍使用CSS3的transform属性的scale值来解决这个问题,这也是码分最常用的解决方案。下方的码分源码中说明1px(线条/边框)解决方案
效果对比(效果有点问题,请复制下方源码查看最终效果)源码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,码分initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"><metaname="author"content="helang.love@qq.com"><title>移动端1px(线条/边框)解决方案</title><styletype="text/css">body{ margin:0;padding:0;font-size:px;color:#;font-family:'MicrosoftYaHei','TimesNewRoman',Times,serif;}/*线条*/.list{ margin:px;list-style:none;line-height:px;padding:0;}.list>li{ padding:0;position:relative;}.list>li:not(:first-child):after{ /*CSS匹配非第一个直接子元素*/content:"";display:block;height:0;border-top:#solid1px;width:%;position:absolute;top:0;right:0;transform:scaleY(0.5);/*将1px的线条缩小为原来的%*/}/*边框*//*其他作者可能会通过设置4个边的线条凑出边框线的效果,这样做不仅代码不够精简,码分而且调整圆角问题也会非常麻烦*/.button{ line-height:px;text-align:center;margin:px;background-color:#f8f8f8;position:relative;border-radius:4px;}.button:after{ content:"";position:absolute;top:-%;right:-%;bottom:-%;left:-%;border:1pxsolid#;transform:scale(0.5);transform-origin:%%0;box-sizing:border-box;border-radius:8px;/*尺寸缩小%,码分即圆角半径设置为按钮的码分bottlecms源码2倍*/}</style></head><body><ulclass="list"><li>线条1px</li><li>web前端河浪</li><li>helang.love@qq.com</li></ul><divclass="button">边框1px</div></body></html>作者:黄河爱浪邮箱:helang.love@qq.com
BigDecimal转换成String的精度问题
在项目中遇到一个价格展示问题,.的码分商品在购物车中显示为.,源于BigDecimal到String的码分转换中精度丢失。为此,对BigDecimal的精度展示进行了深入研究。
转换方式主要有两种:String.format和price.setScale。首先,采用String.format的原始方法,它依赖于format源码中的fs.print(),尤其printFloat方法,其默认的RoundMode.halfUp策略导致了进位误差。进一步分析,这种模式会自动进行向上取整,conrenthashmap源码造成精度损失。
相比之下,采用price.setScale的方式更具优势。这种方式允许开发者自定义舍入策略,避免了默认进位带来的偏差。在具体实现中,通过divideAndRound方法,可以灵活控制精度。结合toPlainString方法,可以满足各种精度需求,得到更准确的结果。
总的deleger 源码来说,String.format由于其默认的舍入规则可能导致精度问题,而price.setScale则提供了更多选择,能更好地解决精度转换中的困扰,是更推荐的做法。
caffe ä¸ä¸ºä»ä¹bnå±è¦åscaleå±ä¸èµ·ä½¿ç¨
1) è¾å ¥å½ä¸å x_norm = (x-u)/std, å ¶ä¸uåstdæ¯ä¸ªç´¯è®¡è®¡ç®çåå¼åæ¹å·®ã2ï¼y=alphaÃx_norm + betaï¼å¯¹å½ä¸ååçxè¿è¡æ¯ä¾ç¼©æ¾åä½ç§»ãå ¶ä¸alphaåbetaæ¯éè¿è¿ä»£å¦ä¹ çã
é£ä¹caffeä¸çbnå±å ¶å®åªåäºç¬¬ä¸ä»¶äºï¼scaleå±åäºç¬¬äºä»¶äºï¼æ以两è è¦ä¸èµ·ä½¿ç¨ã
ä¸ï¼å¨Caffeä¸ä½¿ç¨Batch Normalizationéè¦æ³¨æ以ä¸ä¸¤ç¹ï¼
1. è¦é åScaleå±ä¸èµ·ä½¿ç¨ã
2. è®ç»çæ¶åï¼å°BNå±çuse_global_stats设置为falseï¼ç¶åæµè¯çæ¶åå°use_global_stats设置为trueã
äºï¼åºæ¬å ¬å¼æ¢³çï¼
Scaleå±ä¸»è¦å®æ top=alpha∗bottom+betatop=alpha∗bottom+betaçè¿ç¨ï¼åå±ä¸ä¸»è¦æ两个åæ°alphaalphaä¸betabeta,
æ±å¯¼ä¼æ¯è¾ç®åã∂y∂x=alpha;∂y∂alpha=x;∂y∂beta=1ã éè¦æ³¨æçæ¯alphaalphaä¸betabetaå为åéï¼é对è¾å ¥çchannelschannelsè¿è¡çå¤çï¼å æ¤ä¸è½ç®åç认å®ä¸ºä¸ä¸ªfloatfloatçå®æ°ã
ä¸ï¼å ·ä½å®ç°è¯¥é¨åå°ç»åæºç å®ç°è§£æscalescaleå±:
å¨Caffe protoä¸ScaleParameterä¸å¯¹Scaleæå¦ä¸å 个åæ°ï¼
1ï¼åºæ¬æååéï¼åºæ¬æååé主è¦å å«äºBiaså±çåæ°ä»¥åScaleå±å®æ对åºééçæ 注工ä½ã
2ï¼åºæ¬æåå½æ°ï¼ä¸»è¦å å«äºLayerSetup,Reshape ,ForwardåBackward ï¼å é¨è°ç¨çæ¶åbias_term为trueçæ¶åä¼è°ç¨biasLayerçç¸å ³å½æ°ã
3ï¼Reshape è°æ´è¾å ¥è¾åºä¸ä¸é´åéï¼Reshapeå±å®æ许å¤ä¸é´åéçsizeåå§åã
4ï¼Forward åå计ç®ï¼åå计ç®ï¼å¨BNä¸å½ç´§è·çBNçå½ä¸åè¾åºï¼å®æä¹ä»¥alphaä¸+biasçæä½ï¼ç±äºalphaä¸biaså为Cçåéï¼å æ¤éè¦å è¿è¡å¹¿æã
5ï¼Backward åå计ç®ï¼ä¸»è¦æ±è§£ä¸ä¸ªæ¢¯åº¦ï¼å¯¹alpha ãbetaåè¾å ¥çbottom(æ¤å¤çtemp)ã
Kubernetes —— Pod 自动水平伸缩源码剖析(上)
ReplicaSet 控制器负责维持指定数量的 Pod 实例正常运行,这个数量通常由声明的工作负载资源对象如 Deployment 中的.spec.replicas字段定义。手动伸缩适用于对应用程序进行预调整,如在电商促销活动前对应用进行扩容,活动结束后缩容。然而,这种方式不适合动态变化的应用负载。
Kubernetes 提供了 Pod 自动水平伸缩(HorizontalPodAutoscaler,arraydeque源码简称HPA)能力,允许定义动态应用容量,容量可根据负载情况变化。例如,当 Pod 的平均 CPU 使用率达到 %,且最大 Pod 运行数不超过 个时,HPA 会触发水平扩展。
HPA 控制器负责维持资源状态与期望状态一致,即使出现错误也会继续处理,直至状态一致,称为调协。控制器依赖 MetricsClient 获取监控数据,包括 Pod 的 CPU 和内存使用情况等。
MetricsClient 接口定义了获取不同度量指标类别的监控数据的能力。实现 MetricsClient 的客户端分别用于集成 API 组 metrics.k8s.io,处理集群内置度量指标,自定义度量指标和集群外部度量指标。
HPA 控制器创建并运行,依赖 Scale 对象客户端、HorizontalPodAutoscalersGetter、Metrics 客户端、HPA Informer 和 Pod Informer 等组件。Pod 副本数计算器根据度量指标监控数据和 HPA 的理想资源使用率,决策 Pod 副本容量的伸缩。
此篇介绍了 HPA 的基本概念和相关组件的创建过程,后续文章将深入探讨 HPA 控制器的调协逻辑。感谢阅读,欢迎指正。
大屏适配的几种方式
在开发中,大屏适配有多种策略可供选择,包括rem、vw/vh、scale方案以及相关的开源组件库。首先,rem方案通过调整HTML根节点的字体大小,实现根据不同屏幕大小的动态适配。vw/vh方案则是基于设计稿的相对百分比,确保在不同分辨率下保持一致的视觉效果。
scale方案针对*(:9)设计稿,提供了两种方法:一是按宽度缩放,适用于对宽度变化敏感的应用;二是动态计算网页宽高比,以便根据屏幕尺寸进行更精准的缩放。开源组件库如autofit.js,利用比例缩放原理,通过调整容器尺寸实现全屏填充,保持布局一致性,适合跨分辨率项目。安装、配置和源码地址可以在其官方文档中找到。
另一种组件是v-scale-screen,专为大屏项目设计,支持宽度、高度和宽高比自适应,适用于React开发者。安装和配置同样需要参考其文档。FitScreen则基于设计草图的像素尺寸,通过缩放实现简单的大屏适配,兼容vue2、vue3和React框架,只需少量代码即可实现。
总的来说,这些方法各有利弊,开发者需要根据项目需求和具体技术栈选择最适合的适配方式。在实际应用中,务必确保在各种屏幕尺寸上都能提供良好的用户体验。
android Matrix.setRotate å postRotateçåºå«
Matrix主è¦ç¨äºå¯¹å¹³é¢è¿è¡å¹³ç§»(Translate)ï¼ç¼©æ¾(Scale)ï¼æ转(Rotate)以åæå(Skew)æä½ã
为ç®åç©éµåæ¢ï¼Androidå°è£ äºä¸ç³»åæ¹æ³æ¥è¿è¡ç©éµåæ¢ï¼å ¶ä¸å æ¬ï¼
setç³»åæ¹æ³ï¼setTranslateï¼setScaleï¼setRotateï¼setSkewï¼è®¾ç½®ï¼ä¼è¦çä¹åçåæ°ã
preç³»åæ¹æ³ï¼preTranslateï¼preScaleï¼preRotateï¼preSkewï¼ç©éµå ä¹ï¼å¦M' = M * T(dx, dy)ã
postç³»åæ¹æ³ï¼postTranslateï¼postScaleï¼postRotateï¼postSkewï¼ç©éµåä¹ï¼å¦M' = T(dx, dy) * Mã
éè¿å°åæ¢ç©éµä¸åå§ç©éµç¸ä¹æ¥è¾¾å°åæ¢çç®çï¼ä¾å¦ï¼
平移ï¼x'=x+txï¼y'=y+tyï¼ï¼
缩æ¾ï¼x'=sx*xï¼y'=sy*yï¼ï¼
æ转ï¼x'=cosβ*x-sinβ*yï¼y'=sinβ*x+cosβ*yï¼ï¼
éæ©éè¦ç¨å°å¦ä¸çä¸è§å½æ°çå ¬å¼ï¼
â sin(α+β)=sinαcosβ+cosαsinβ
â¡cos(α+β)=cosαcosβ-sinαsinβ
å ¬å¼â å¯ä»¥ç±åä½åæ¹æ³ææåå¯å®çæ¨å¯¼åºæ¥ã
æ¨å¯¼è¿ç¨åè§ï¼/s/blog_fcj.html
æåï¼x'=x+k1*yï¼y'=k2*x+yï¼ï¼
//æºç æ件ï¼external\skia\legacy\src\core\SkMatrix.cpp
#define SK_Scalar1 (1.0f)
#define kMatrixElem SK_Scalar1
typedef float SkScalar;
#define SkScalarMul(a, b) ((float)(a) * (b))
enum {
kMScaleX, kMSkewX, kMTransX,
kMSkewY, kMScaleY, kMTransY,
kMPersp0, kMPersp1, kMPersp2
};
void SkMatrix::reset() {
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //å ¶å¼ä¸º1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //å ¶å¼ï¼å ¨ä¸º0
fMat[kMPersp2] = kMatrixElem; //å ¶å¼ä¸º1
this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
}
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] = dx; //以æ°å¼dxè¦çåå¼ï¼åå¼æ æäº
fMat[kMTransY] = dy;
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //å ¶å¼ä¸º1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //å ¶å¼ï¼å ¨ä¸º0
fMat[kMPersp2] = kMatrixElem; //å ¶å¼ä¸º1
this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
} else {
this->reset();
}
}
bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->preConcat(m); //ç©éµçå ä¹è¿ç®
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
SkScalarMul(fMat[kMSkewX], dy); //å ä¹ï¼éè¦ç©éµè¿ç®è¿
fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
SkScalarMul(fMat[kMScaleY], dy);
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->postConcat(m); //ç©éµçåä¹è¿ç®
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += dx; //åä¹ï¼ç´æ¥å æ°å¼dxå³å¯
fMat[kMTransY] += dy;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::preConcat(