摘要:注冊陀螺儀傳感器首先注冊陀螺儀傳感器根據具體需要自己設置靈敏度,當然越靈敏,越耗電。注冊陀螺儀傳感器,并設定傳感器向應用中輸出的時間間隔類型是微秒微秒最快。
簡介
大家好我是張鵬輝(道長)人如其名,我是天橋上算命的,轉發這條博文,接下來一個月會有意想不到的驚喜發生。
最近微博上的全景圖火了,所以決定實現一下。
工程里面圖片資源來自網絡,如有侵權請聯系我,馬上刪除
當然實現的方式很多比如OpenCV、u3d等。
這里提供三種方式實現:
OpenGL ES
GoogleCardboard(Google VR)上面的一個集成模塊,我們只使用里面展示全景圖部分模塊
Three.js(利用前端姿勢)WebView混合開發
三種姿勢孰強孰弱,根據需求你們自己判斷!我會在結尾給出一些建議,多說無益開擼
先看下三種實現的效果:
1.OpenGL ES
2.Google VR(全景圖模塊)
第一種 OpenGL ES3.Three.js(利用前端姿勢)WebView混合開發
第一種方式使用OpenGL來實現(上面gif圖截取因為博客限制上傳圖片的大小,我壓縮了,看起來有些卡其實很流暢的)
可以看到支持旋轉手機查看、或者拖動圖片查看、可以看到右邊中心部分有個指示器會隨著角度變化而變化并且點擊可以還原起始位置。
Step 1有些小伙伴懶得看原理,直接就想拿來用所以我先說集成方式吧!
在build.gradle 文件中添加庫依賴:
allprojects { repositories { maven { url "https://jitpack.io" } } }Step 2.Add the dependency
在 build.gradle 文件中添加庫依賴:
dependencies { compile "com.github.CN-ZPH:weibo360panorama:v1.0.1" }
build.gradle 完整代碼:
apply plugin: "com.android.application" android { compileSdkVersion 26 buildToolsVersion "26.0.1" defaultConfig { applicationId "com.zph.three360panorama" minSdkVersion 19 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } allprojects { repositories { maven { url "https://jitpack.io" } } } } dependencies { compile fileTree(include: ["*.jar"], dir: "libs") androidTestCompile("com.android.support.test.espresso:espresso-core:2.2.2", { exclude group: "com.android.support", module: "support-annotations" }) compile "com.android.support:appcompat-v7:26.+" compile "com.android.support.constraint:constraint-layout:1.0.2" compile "com.android.support:design:26.+" compile "com.github.CN-ZPH:weibo360panorama:v1.0.1" compile "com.google.vr:sdk-panowidget:1.80.0" testCompile "junit:junit:4.12" compile files("libs/tbs_sdk_thirdapp_v3.3.0.1045_43300.jar") }Step 3.創建布局文件.XML
Step 4.傳入你的全景圖
*R.drawable.imggugong 這張全景圖傳到控件里面
public class MainActivity extends AppCompatActivity { private GLPanorama mGLPanorama; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化全景控件 mGLPanorama= (GLPanorama) findViewById(R.id.mGLPanorama); //傳入你的全景圖 mGLPanorama.setGLPanorama(R.drawable.imggugong); } }OK現在你可以測試玩玩了(別用模擬器玩咔咔報錯就來找我)。 二.分析
首先我們需要了解全景圖是什么東西,全景圖是一種廣角圖。通過全景播放器可以讓觀看者身臨其境地進入到全景圖所記錄的場景中去,通常標準的全景圖是一張2:1的圖像,其背后的實質就是等距圓柱投影。等距圓柱投影是一種將球體上的各個點投影到圓柱體的側面上的一種投影方式,投影完之后再將它展開就是一張2:1的長方形的圖像。比較常見的就是應用在地圖上的投影。
得到全景圖后那我們就需要展示了,看到旁邊地球了嗎?
怎么展示呢簡單來說就是把全景圖片整個貼到一個球體上。
好了知道原理那我們就該考慮在android上怎么實現了,在android中繪制3d圖形可以使用OpenGL (就不說OpenGL 基礎了想看的自己百度一大堆資料)。
引用tim_shadow大佬的關于全景圖一篇文章介紹
在OpenGL ES中基本上所有的立體圖像都是通過一個個的小三角形拼接而成我們知道球面上面的每一個點(P(x,y,z))都會滿足方程組(球的極坐標方程):
x = r sin(a) cos(b)
y = r * cos(a)
z = r sin(a)sin(b)
其中 r為球的半徑,a為線段 OP與 z軸正方向所夾角,b為 OP在xoy平面的投影 OP‘ 與x的正方向所夾角
我們可以根據這個方程組,通過控制∠a和∠b的變化,從上到下,逆時針的取得我們需要用來組合稱三角形的點,然后我們需要將全景圖片上的點與我們在球上面選取的點一一對應起來(注意:球的坐標是3維坐標,圖片的坐標是2維坐標)
球上面的點與圖片上面的點一一對應起來。
紋理和圖片綁定繪制到屏幕上
int[] textures = new int[1]; glGenTextures(1, textures, 0); int textureId = textures[0]; glBindTexture(GL_TEXTURE_2D, textureId); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); InputStream is = context.getResources().openRawResource(drawableId); Bitmap bitmapTmp; try { bitmapTmp = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmapTmp, 0); bitmapTmp.recycle();2.利用傳感器讓球隨著手機轉動而轉動
第一想到的就是重力感應傳感器,可是只能獲得我們向那個位置偏移的方向,顯然不可能滿足我們旋轉的需求,使用陀螺儀傳感器。
陀螺儀就是內部有一個陀螺,它的軸由于陀螺效應始終與初始方向平行,這樣就可以通過與初始方向的偏差計算出實際方向。
陀螺儀對設備旋轉角度的檢測是瞬時的而且是非常精確的。
首先注冊陀螺儀傳感器根據具體需要自己設置靈敏度,當然越靈敏,越耗電。
注冊陀螺儀傳感器,并設定傳感器向應用中輸出的時間間隔類型是SensorManager.SENSOR_DELAY_GAME(20000微秒)
SensorManager.SENSOR_DELAY_FASTEST(0微秒):最快。最低延遲,一般不是特別敏感的處理不推薦使用,該模式可能在成手機電力大量消耗,由于傳遞的為原始數據,算法不處理好會影響游戲邏輯和UI的性能
SensorManager.SENSOR_DELAY_GAME(20000微秒):游戲。游戲延遲,一般絕大多數的實時性較高的游戲都是用該級別
SensorManager.SENSOR_DELAY_NORMAL(200000微秒):普通。標準延時,對于一般的益智類或EASY級別的游戲可以使用,但過低的采樣率可能對一些賽車類游戲有跳幀現象
SensorManager.SENSOR_DELAY_UI(60000微秒):用戶界面。一般對于屏幕方向自動旋轉使用,相對節省電能和邏輯處理,一般游戲開發中不使用
我這里為了測試設置了SENSOR_DELAY_FASTEST,實際使用建議用SENSOR_DELAY_GAME
private void initSensor() { sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); sensorManager.registerListener(this, gyroscopeSensor, SensorManager.SENSOR_DELAY_FASTEST); }2.獲得傳感器數據
當傳感器的值發生變化時,例如磁阻傳感器方向改變時會調用OnSensorChanged(). 當傳感器的精度發生變化時會調用OnAccuracyChanged()方法。
從 x、y、z 軸的正向位置觀看處于原始方位的設備,如果設備逆時針旋轉,將會收到正值;否則,為負值
得到兩次檢測到手機旋轉的時間差(納秒),并將其轉化為秒
將手機在各個軸上的旋轉角度相加,即可得到當前位置相對于初始位置的旋轉弧度,將弧度轉化為角度
@Override public void onSensorChanged(SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE) { if (timestamp != 0) { final float dT = (sensorEvent.timestamp - timestamp) * NS2S; angle[0] += sensorEvent.values[0] * dT; angle[1] += sensorEvent.values[1] * dT; angle[2] += sensorEvent.values[2] * dT; float anglex = (float) Math.toDegrees(angle[0]); float angley = (float) Math.toDegrees(angle[1]); float anglez = (float) Math.toDegrees(angle[2]); Sensordt info = new Sensordt(); info.setSensorX(angley); info.setSensorY(anglex); info.setSensorZ(anglez); Message msg = new Message(); msg.what = 101; msg.obj = info; mHandler.sendMessage(msg); } timestamp = sensorEvent.timestamp; } }3.設置填充球的Y,X的角度
每次獲得角度數據后只需要y,x的值計算位移的值
因為全景圖上下旋轉會翻轉整個圖所以我這里設置了上下只能偏移50f,如果不限制你可以去掉
mBall.yAngle += dx 2.0f;這里2.0也就是陀螺儀傳過來的值乘以得出偏移的角度,數值越大,每次偏移更快!
Sensordt info = (Sensordt) msg.obj; float y = info.getSensorY(); float x = info.getSensorX(); float dy = y - mPreviousY;// 計算觸控筆Y位移 float dx = x - mPreviousX;// 計算觸控筆X位移 mBall.yAngle += dx * 2.0f;// 設置填充橢圓繞y軸旋轉的角度 mBall.xAngle += dy * 0.5f;// 設置填充橢圓繞x軸旋轉的角度 if (mBall.xAngle < -50f) { mBall.xAngle = -50f; } else if (mBall.xAngle > 50f) { mBall.xAngle = 50f; } mPreviousY = y; mPreviousX = x;3.加入手勢操控,拖動圖片轉動
加入手勢這里沒什么好說的了,就是重寫onTouchEvent()方法。
這里唯一要注意的就是,當手指點擊屏幕的時候要關閉陀螺儀傳感器的監聽不然會引起沖突。當手指離開屏幕,重新監聽陀螺儀傳感器。
和上面也一樣只是這里換成獲取手指偏移角度,而不是傳感器的數值,直接看代碼。
public boolean onTouchEvent(MotionEvent e) { sensorManager.unregisterListener(this); float y = e.getY(); float x = e.getX(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dy = y - mPreviousYs;// 計算觸控筆Y位移 float dx = x - mPreviousXs;// 計算觸控筆X位移 mBall.yAngle += dx * 0.3f;// 設置填充橢圓繞y軸旋轉的角度 mBall.xAngle += dy * 0.3f;// 設置填充橢圓繞x軸旋轉的角度 if (mBall.xAngle < -50f) { mBall.xAngle = -50f; } else if (mBall.xAngle > 50f) { mBall.xAngle = 50f; } Log.i("zphsas", "mHandler *** mPreviousY" + mBall.yAngle); Log.i("zphsas", "mHandler *** mPreviousx" + mBall.xAngle); rotate(); break; case MotionEvent.ACTION_UP: sensorManager.registerListener(this, gyroscopeSensor, SensorManager.SENSOR_DELAY_FASTEST); break; } mPreviousYs = y;// 記錄觸控筆位置 mPreviousXs = x;// 記錄觸控筆位置 return true; }4.加入指示器
指示器這里弄了一個角標指示當前在全景圖的角度,并且點擊還原起始角度。
可以想象同樣是獲取角度,我們直接放在全景圖改變的地方,讓指示器一起改變,而我們改變的地方只有2個陀螺儀和拖動屏幕。
我這里指示器放了一張圖也就是一個 ImageView 控件
1.為指示器加入動畫跟隨全景圖一起轉
private void rotate() { RotateAnimation anim = new RotateAnimation(predegrees, -mBall.yAngle, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim.setDuration(200); img.startAnimation(anim); predegrees = -mBall.yAngle;//記錄這一次的起始角度作為下次旋轉的初始角度 }
2.點擊指示器還原起始位置
當點擊還原的時候,我一開始是直接恢復起始位置可是太生硬了,通過獲取當前旋轉的角度,逆向旋轉,慢慢還原,讓其有個過渡的效果。
Y軸=旋轉的角度-90f(起始角度)/10f(每次偏移多少,經過我多次嘗試10f在我的手機上剛剛好);
得到我們總共偏移幾次可以復位;
X軸同理,因為我上面限制了X軸的最大偏移,這里就不就算X軸了,不過在完成的同時直接復位X軸。(只是沒有過渡的效果),你可以加上。
我設置的起始角度是90f和0f,也就是X,Y軸的起始點
mHandlers.postDelayed(this, 16);
這行代碼就是多少毫秒復位一次。
看代碼:
private void zero() { yy = (int) ((mBall.yAngle - 90f) / 10f); mHandlers.post(new Runnable() { @Override public void run() { if (yy != 0) { if (yy > 0) { mBall.yAngle = mBall.yAngle - 10f; mHandlers.postDelayed(this, 16); yy--; } if (yy < 0) { mBall.yAngle = mBall.yAngle + 10f; mHandlers.postDelayed(this, 16); yy++; } } else { mBall.yAngle = 90f; } mBall.xAngle = 0f; } }); }至此第一種OpenGL ES方式核心代碼分析完畢,有不明白的地方可以找我 第二種 Google VR
第二種也就是谷歌官方為移動平臺下VR解決方案,有興趣的可以點開下面鏈接玩玩,我們只使用其中全景圖模塊。
一.使用 Step 1.Add the dependencyGoogle VR主頁:https://developers.google.com...
Google VR for Android github地址:https://github.com/googlevr/g...
目前GitHub上最新版本號為1.8.0,我這里也用最新的了。
最低支持到 minSdkVersion 19 也就是Android 4.4.0
在 build.gradle 文件中添加庫依賴:
dependencies { compile "com.google.vr:sdk-panowidget:1.80.0" }Step 2.創建布局文件.XML
Step 3.AndroidManifest中添加權限
Step 4.Activity中初始化組件//因為全景圖較大,所以在application下申請更多空間,但是作為一個有節操的碼農建議你不要這么干。
//初始化VR圖片 private void initVrPaNormalView() { mVrPanoramaView = (VrPanoramaView) findViewById(R.id.mVrPanoramaView); paNormalOptions = new VrPanoramaView.Options(); paNormalOptions.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER; // mVrPanoramaView.setFullscreenButtonEnabled (false); //隱藏全屏模式按鈕 mVrPanoramaView.setInfoButtonEnabled(false); //設置隱藏最左邊信息的按鈕 mVrPanoramaView.setStereoModeButtonEnabled(false); //設置隱藏立體模型的按鈕 mVrPanoramaView.setEventListener(new ActivityEventListener()); //設置監聽 //加載本地的圖片源 mVrPanoramaView.loadImageFromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.andes), paNormalOptions); //設置網絡圖片源 // panoWidgetView.loadImageFromByteArray(); } private class ActivityEventListener extends VrPanoramaEventListener { @Override public void onLoadSuccess() {//圖片加載成功 } @Override public void onLoadError(String errorMessage) {//圖片加載失敗 } @Override public void onClick() {//當我們點擊了VrPanoramaView 時候觸發 super.onClick(); } @Override public void onDisplayModeChanged(int newDisplayMode) { super.onDisplayModeChanged(newDisplayMode); } }第二種到這里已經可以顯示玩玩了,也沒什么可分析的,都是官方提供的sdk,會調用相關的方法就好了,具體都有那些方法接口,最好的文檔永遠都是官方提供的,上面已經給出了鏈接,最好自己把GitHub上的官方提供的demo拿下來跑一遍,我就不多介紹了。 第三種 Three.js(利用前端姿勢)WebView混合開發
Three.js是JavaScript編寫的WebGL第三方庫。提供了非常多的3D顯示功能。
Android下相信很多人都多少做過前端開發,現在很多應用程序都是基于前端H5/RN/小程序等來玩的。
當然我們全景圖也可以放到前端來實現,套個WebView利用JavaScript與Android交互來實現一部分功能。
一.使用 Step 1.添加x5 SDK考慮到在多種機型兼容性,還有原生WebView的一些坑,我這里使用騰訊的X5內核的WebView。
到x5官網下載最新的sdk得到一個jar包
我在這的是3.3.0版本的。
將下載好的jar包放到你的工程libs目錄下
在 build.gradle 文件中添加庫依賴:
dependencies { compile files("libs/tbs_sdk_thirdapp_v3.3.0.1045_43300_sharewithdownload_withoutGame_obfs_20170605_170212.jar") }Step 2.AndroidManifest.xml里加入權限聲明
Step 3.APPAplication中X5內核初始化
public class APPAplication extends Application { @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); //搜集本地tbs內核信息并上報服務器,服務器返回結果決定使用哪個內核。 QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() { @Override public void onViewInitFinished(boolean arg0) { // TODO Auto-generated method stub //x5內核初始化完成的回調,為true表示x5內核加載成功,否則表示x5內核加載失敗,會自動切換到系統內核。 } @Override public void onCoreInitFinished() { // TODO Auto-generated method stub } }; //x5內核初始化接口 QbSdk.initX5Environment(getApplicationContext(), cb); } }Step 4..創建布局文件.XML
Step 5.下載Three.js
下載地址:https://threejs.org/
或者去GitHub從我的項目中找今天代碼都會放到GitHub上
Step 6.編寫HTML文件
在 assets 目錄下創建一個html文件展示全景圖
引入Threejs
panorama:"https://gw.alicdn.com/tfs/TB1...", 這行就是你的全景圖地址
你可以使用js交互將你的地址傳到HTML上
直接上代碼了:
Step 7.Activity調用HTMLPhoto Sphere Viewer
很簡單就是把系統的WebView換成Tencent_Webview其他類似
public class WebViewActivity extends AppCompatActivity { private com.tencent.smtt.sdk.WebView tencent_webview; private String url = "file:///android_asset/admin.html"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web_view); initView(); } @SuppressLint("SetJavaScriptEnabled") private void initView() { tencent_webview = (WebView) findViewById(R.id.web); tencent_webview.loadUrl(url); WebSettings webSettings = tencent_webview.getSettings(); webSettings.setJavaScriptEnabled(true); tencent_webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return true; } }); } }
最后附上插件的可配置參數:
panorama:必填參數,全景圖的路徑。 container:必填參數,放置全景圖的div元素。 autoload:可選,默認值為true,true為自動調用全景圖,false為在后面加載全景圖(通過.load()方法)。 usexmpdata:可選,默認值為true,如果Photo Sphere Viewer必須讀入XMP數據則為true。 default_position:可選,默認值為{},定義默認的位置,及用戶看見的第一個點,例如:{long: Math.PI, lat: Math.PI/2}。 min_fov:可選,默認值為30,觀察的最小區域,單位degrees,在1-179之間。 max_fov:可選,默認值為90,觀察的最大區域,單位degrees,在1-179之間。 allow_user_interactions:可選,默認值為true,設置為false則禁止用戶和全景圖交互(導航條不可用)。 tilt_up_max:可選,默認值為Math.PI/2,向上傾斜的最大角度,單位radians。 tilt_down_max:可選,默認值為Math.PI/2,向下傾斜的最大角度,單位radians。 zoom_level:可選,默認值為0,默認的縮放級別,值在0-100之間。 long_offset:可選,默認值為PI/360,mouse/touch移動時每像素經過的經度值。 lat_offset:可選,默認值為PI/180,mouse/touch移動時每像素經過的緯度值。 time_anim:可選,默認值為2000,全景圖在time_anim毫秒后會自動進行動畫。(設置為false禁用它) theta_offset:過時的選項,可選,默認值為1440,自動動畫時水平方向的速度。 anim_speed:可選,默認值為2rpm,動畫的速度,每秒/分鐘多少radians/degrees/revolutions。 navbar:可選值,默認為false。顯示導航條。 navbar_style:可選值,默認為{}。導航條的自定義樣式。下面是可用的樣式列表: backgroundColor:導航條的背景顏色,默認值為rgba(61, 61, 61, 0.5)。 buttonsColor:按鈕的前景顏色,默認值為transparent。 activeButtonsBackgroundColor:按鈕激活狀態的背景顏色,默認值為rgba(255, 255, 255, 0.1)。 buttonsHeight:按鈕的高度,單位像素,默認值為20。 autorotateThickness:autorotate圖標的厚度,單位像素,默認值為1。 zoomRangeWidth:縮放的范圍,單位顯示,默認值50。 zoomRangeThickness:縮放的范圍的厚度,單位像素,默認值1。 zoomRangeDisk:縮放范圍的圓盤直徑,單位像素,默認值為7。 fullscreenRatio:全屏圖標的比例,默認值為3/4。 fullscreenThickness:全屏圖標的厚度,單位像素,默認值為2。 loading_msg:可選,默認值為Loading…,圖片加載時的提示文字。 loading_img:可選,默認值為null,在加載時顯示的圖片的路徑。 size:可選,默認值null,全景圖容器的最終尺寸。例如:{width: 500, height: 300}。 onready:可選值,默認值為null。當全景圖準備就緒并且第一張圖片顯示時的回調函數。總結
三種方式都實現完了,不用擔心今天所有代碼都會放在GitHub上。
三種方式具體你使用哪種我還是沒有推薦的
這里只是一張圖,你可以多張圖實現來完成簡單的全景街景功能!點擊圖片某個區域,跳轉到下一個街景的圖,包括百度地圖里面也是一張張全景圖拼接而成。
項目源碼下載地址:第一種我會在后續繼續完善加入更多的可選參數,你們有興趣也可以自己優化。
第二種是谷歌VR模塊的沒什么好說的,畢竟官方倆字就夠了。
第三種跨平臺最好的,畢竟是個網頁。而我們第三種使用了騰訊X5內核來玩,但是還可以在優化,消耗不小,我建議你多帶帶給WebView分配一個進程和你的業務分離。
拿著我的保溫杯,泡一杯枸杞,我們下篇文章再會
https://github.com/CN-ZPH/
覺得不錯請點一個star蛤!
有問題下面留言評論,我看到會回復。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70279.html
摘要:透視即是以現實的視角來看屏幕上的事物,從而展現的效果。旋轉則不再是平面上的旋轉,而是三維坐標系的旋轉,就包括軸,軸,軸旋轉。必須與屬性一同使用,而且只影響轉換元素。可自由轉載引用,但需署名作者且注明文章出處。 showImg(https://segmentfault.com/img/bVzJoZ); 話不多說,先上demo 酷炫css3走馬燈/正方體動畫: https://bupt-...
摘要:透視即是以現實的視角來看屏幕上的事物,從而展現的效果。旋轉則不再是平面上的旋轉,而是三維坐標系的旋轉,就包括軸,軸,軸旋轉。必須與屬性一同使用,而且只影響轉換元素。可自由轉載引用,但需署名作者且注明文章出處。 showImg(https://segmentfault.com/img/bVzJoZ); 話不多說,先上demo 酷炫css3走馬燈/正方體動畫: https://bupt-...
摘要:阿里云是國內云服務器市場的龍頭,性價比高,速度快又安全,是站長建站首選的云服務器之一。作為一個老司機,福利吧也和大家分享一下我的阿里云推廣經驗,教大家如何免費推廣云大使。阿里云是國內云服務器市場的龍頭,性價比高,速度快又安全,是站長建站首選的云服務器之一。福利吧使用的也是阿里云服務器,是折騰了很多次網站搬家后,才選擇了阿里云。身邊好幾個站長最后都殊途同歸,用了阿里云,可見阿里云服務器性能確實...
摘要:淘寶造物節的活動頁就是全景的一個很贊的頁面,它將全景圖分割成等份,相鄰的元素構成的夾角,相鄰兩側面相對于棱柱中心所構成的夾角。 本文轉自凹凸實驗室:https://aotu.io/notes/2016/08... showImg(https://segmentfault.com/img/remote/1460000011381045); 前言 3D 全景并不是什么新鮮事物了,但以前...
閱讀 2955·2021-11-23 09:51
閱讀 3781·2021-11-22 15:29
閱讀 3240·2021-10-08 10:05
閱讀 1558·2021-09-22 15:20
閱讀 972·2019-08-30 15:56
閱讀 1074·2019-08-30 15:54
閱讀 738·2019-08-26 11:54
閱讀 2638·2019-08-26 11:32