概述



U3D提供了一套拓展编辑器的接口,可以用于直接在编辑器非播放模式运行程序。常用于运行一些工具程序,例如资源管理。在做技能编辑器等工具程序时,也可以使用运行模式接口会比较简单(这样也方便开放游戏创意工坊给玩家)。使用编辑器去做一些渲染相关的预览(如粒子系统,动画预览)会麻烦一点,有时候需要查询和反射使用U3D引擎未暴露的接口。

U3D编辑器相关官方文档查询链接:https://docs.unity3d.com/cn/current/Manual/GUIScriptingGuide.html

业务需求分析



这是常用的一些需求和接口,多数的用法比较简单的在这里简单介绍一下。

OnGUI

代码化在视口绘制UI,常用于绘制一些DebugUI,如官方示例:

OnGUI官方介绍

  1. using UnityEngine;
  2. using System.Collections;
  3. public class GUITest : MonoBehaviour {
  4. void OnGUI ()
  5. {
  6. // 创建背景框
  7. GUI.Box(new Rect(10,10,100,90), "Loader Menu");
  8. // 创建第一个按钮。如果按下此按钮,则会执行 Application.Loadlevel (1)
  9. if(GUI.Button(new Rect(20,40,80,20), "Level 1"))
  10. {
  11. Application.LoadLevel(1);
  12. }
  13. // 创建第二个按钮。
  14. if(GUI.Button(new Rect(20,70,80,20),"Level 2"))
  15. {
  16. Application.LoadLevel(2);
  17. }
  18. }
  19. }

Editor和ExecuteInEditMode特性

  • ExecuteInEditMode特性:让脚本在编辑器模式运行。
  • Editor:封装一些UI绘制的接口,如(重新OnInspectorGUI以在Inspector窗口绘制UI界面)。

Editor和ExecuteInEditMode特性相关官方介绍

EditorWindow

继承EditorWindow重写以在编辑器创建绘制一个独立的编辑器窗口。

  1. using UnityEditor;
  2. using UnityEngine;
  3. public class MyWindow : EditorWindow
  4. {
  5. string myString = "Hello World";
  6. bool groupEnabled;
  7. bool myBool = true;
  8. float myFloat = 1.23f;
  9. // 将名为"My Window"的菜单项添加到 Window 菜单
  10. [MenuItem("Window/My Window")]
  11. public static void ShowWindow()
  12. {
  13. //显示现有窗口实例。如果没有,请创建一个。
  14. EditorWindow.GetWindow(typeof(MyWindow));
  15. }
  16. void OnGUI()
  17. {
  18. GUILayout.Label ("Base Settings", EditorStyles.boldLabel);
  19. myString = EditorGUILayout.TextField ("Text Field", myString);
  20. groupEnabled = EditorGUILayout.BeginToggleGroup ("Optional Settings", groupEnabled);
  21. myBool = EditorGUILayout.Toggle ("Toggle", myBool);
  22. myFloat = EditorGUILayout.Slider ("Slider", myFloat, -3, 3);
  23. EditorGUILayout.EndToggleGroup ();
  24. }
  25. }

EditorWindow官方示例

Serializable属性绘制器

Serializable U3D官方翻译为属性绘制器,字面意思是可被序列化的。大概的效果是被Serializable特性标记可以被U3D序列化并在U3D进行绘制和提供更方便的操作,如下:

  1. using System;
  2. using UnityEngine;
  3. enum IngredientUnit { Spoon, Cup, Bowl, Piece }
  4. // 自定义 Serializable 类
  5. [Serializable]
  6. public class Ingredient
  7. {
  8. public string name;
  9. public int amount = 1;
  10. public IngredientUnit unit;
  11. }
  12. public class Recipe : MonoBehaviour
  13. {
  14. public Ingredient potionResult;
  15. public Ingredient[] potionIngredients;
  16. }

属性绘制器官方介绍

外观风格/皮肤

GUIStyle和GUISkin提供了接口来定制化UI绘制的外观风格,区别在于GUIStyle常用于某个控件的风格绘制,而GUISkin则会应用于其下文中所有控件的绘制,具体使用细节见官方介绍

GUISkin官方介绍

GUIStyle官方介绍

PreviewRenderUtility 预览窗口渲染工具

PreviewRenderUtility 个人认为它是一个预览窗口的渲染工具类,官方对其介绍几乎没有。但是在EditorWindow、Inspector窗口预览模型、动画、粒子特效会用到。例如这个特效的预览下文会具体介绍:

常用控件速查表

名称 代码 示例
Label GUI.Label (new Rect (25, 25, 100, 30), "Label");
Button if (GUI.Button (new Rect (25, 25, 100, 30), "Button"))
TextField 单行输入框 str = GUI.TextField (new Rect (25, 25, 100, 30), str);
TextArea 多行输入框 str = GUI.TextArea (new Rect (25, 25, 100, 30), str);
Toggle 勾选框 b = GUI.Toggle (new Rect (25, 25, 100, 30), toggleBool, "Toggle");
HorizontalSlider 水平滑块 h = GUI.HorizontalSlider (new Rect (25, 25, 100, 30), hSliderValue, 0.0f, 10.0f);
Toolbar 页签 Idx = GUI.Toolbar (new Rect (25, 25, 250, 30), Idx, BtnNames);
SelectionGrid 平铺列表 Idx = GUI.SelectionGrid (new Rect (25, 25, 300, 60), Idx, Names, Cow);
ScrollView 滚动列表 pos = GUI.BeginScrollView (rect, scrollViewVector, rectContent);
//XXX
GUI.EndScrollView();
Window 小窗口 w = GUI.Window (0, wRect, drawDele, "win");

注意手动排版使用GUI.XXX,自动排版使用GUILayout.XXX

布局速查表

布局的一般用法是,例如组Group

GUI.BeginGroup

//控件A

//控件B ...

GUI.EndGroup



using (new GroupScope)

{

//控件A

//控件B ...

}

布局 用法 预览
组 Group 固定相对位置
区域 Area 用于自动布局一组控件,与组类似 -
水平布局 Horizontal 水平布局一组控件
垂直布局 Vertical 垂直布局一组控件

GUILayoutOption可以某些重写自动布局参数,例如:

GUILayout.Button ("My width has been overridden", GUILayout.Width (95));

GUILayout.Width重写了自动布局这个按钮的宽

特效预览窗口

U3D自带的特效预览方式是拖到Scene窗口上,有的时候做编辑器(例如技能编辑器)时需要预览的特效,切来切去太麻烦了。而且U3D拖到Scene才能预览这种方式也很麻烦,也可以自己拓展选中特效在Hir上预览。

关键点

  • 使用反射调用库函数绑定特效
  • 使用prevRU渲染GameObj

代码示例

LibUtil 调用库函数

  1. public class LibUtil
  2. {
  3. public static Type ParticleSystemEditorUtils
  4. {
  5. get
  6. {
  7. var assembly = Assembly.GetAssembly(typeof(Editor));
  8. return assembly.GetType("UnityEditor.ParticleSystemEditorUtils");
  9. }
  10. }
  11. public static ParticleSystem lockedParticleSystem
  12. {
  13. get
  14. {
  15. var info = ParticleSystemEditorUtils.GetProperty("lockedParticleSystem", BindingFlags.Static | BindingFlags.NonPublic);
  16. return (ParticleSystem)info.GetValue(null, null);
  17. }
  18. set
  19. {
  20. var info = ParticleSystemEditorUtils.GetProperty("lockedParticleSystem", BindingFlags.Static | BindingFlags.NonPublic);
  21. info.SetValue(null, value, null);
  22. }
  23. }
  24. public static bool editorIsScrubbing
  25. {
  26. set
  27. {
  28. var info = ParticleSystemEditorUtils.GetProperty("playbackIsScrubbing", BindingFlags.Static | BindingFlags.NonPublic);
  29. info.SetValue(null, value, null);
  30. }
  31. }
  32. public static float editorPlaybackTime
  33. {
  34. get
  35. {
  36. var info = ParticleSystemEditorUtils.GetProperty("playbackTime", BindingFlags.Static | BindingFlags.NonPublic);
  37. return (float)info.GetValue(null, null);
  38. }
  39. set
  40. {
  41. var info = ParticleSystemEditorUtils.GetProperty("playbackTime", BindingFlags.Static | BindingFlags.NonPublic);
  42. info.SetValue(null, value, null);
  43. }
  44. }
  45. public static void StopEffect()
  46. {
  47. var assembly = Assembly.GetAssembly(typeof(Editor));
  48. var util = assembly.GetType("UnityEditor.ParticleSystemEffectUtils");
  49. var info = util.GetMethod("StopEffect", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { }, new ParameterModifier[] { });
  50. info.Invoke(null, null);
  51. }
  52. }

拓展ObjectPreview

  1. public class MyView : ObjectPreview
  2. {
  3. PreviewRenderUtility prevRU;
  4. GameObject ins;
  5. Mesh fm;
  6. Texture2D ft;
  7. Material fma;
  8. static int prevCulLay = 31;
  9. bool isRunning = false;
  10. Editor e;
  11. ParticleSystem ps
  12. {
  13. get
  14. {
  15. var p = ins.GetComponent<ParticleSystem>();
  16. return p;
  17. }
  18. }
  19. public void BindEditor(Editor editor)
  20. {
  21. e = editor;
  22. }
  23. public void Repaint()
  24. {
  25. if (e != null)
  26. e.Repaint();
  27. }
  28. void DrawPlayBtn()
  29. {
  30. if (GUILayout.Button("Play"))
  31. Play();
  32. if (GUILayout.Button("Stop"))
  33. Stop();
  34. }
  35. public override void OnPreviewSettings()
  36. {
  37. using (new EditorGUILayout.HorizontalScope())
  38. {
  39. DrawPlayBtn();
  40. }
  41. }
  42. public void Play()
  43. {
  44. var p = ps;
  45. Stop();
  46. if (p != null && isRunning == false)
  47. {
  48. isRunning = true;
  49. LibUtil.lockedParticleSystem = p;
  50. p.Play();
  51. LibUtil.editorIsScrubbing = false;
  52. EditorApplication.update += Update;
  53. }
  54. }
  55. public void Stop()
  56. {
  57. var p = ps;
  58. if (p != null && isRunning == true)
  59. {
  60. LibUtil.editorIsScrubbing = false;
  61. LibUtil.editorPlaybackTime = 0f;
  62. LibUtil.StopEffect();
  63. isRunning = false;
  64. p.Stop();
  65. EditorApplication.update -= Update;
  66. }
  67. }
  68. //PreviewRenderUtility渲染
  69. public void Render()
  70. {
  71. var flag = StartLight();
  72. var viewDir = new Vector2(120f, -20f);
  73. var cam = prevRU.camera;
  74. var zoomFactor = 1.0f;
  75. var avatarScale = 1.0f;
  76. cam.nearClipPlane = 0.5f * zoomFactor;
  77. cam.farClipPlane = 100f * avatarScale;
  78. Quaternion rot = Quaternion.Euler(-viewDir.y, -viewDir.x, 0f);
  79. var camPos = rot * (Vector3.forward * -5.5f * zoomFactor); // + bodyPos + pivotPosOff;
  80. cam.transform.position = camPos;
  81. cam.transform.rotation = rot;
  82. var refIns = ins;
  83. Matrix4x4 mat = Matrix4x4.TRS(refIns.transform.position, Quaternion.identity, Vector3.one * 5f * avatarScale);
  84. var refPos = refIns.transform.position;
  85. fma.mainTextureOffset = -new Vector2(refPos.x, refPos.z) * 5f * 0.08f * (1f / avatarScale);
  86. fma.SetVector("_Alphas", new Vector4(0.5f * 1f, 0.3f * 1f, 0f, 0f));
  87. Graphics.DrawMesh(fm, mat, fma, prevCulLay, cam, 0);
  88. cam.Render();
  89. EndLighting(flag);
  90. }
  91. public override void OnPreviewGUI(Rect r, GUIStyle background)
  92. {
  93. if (prevRU == null)
  94. {
  95. CreatePrevRU();
  96. }
  97. prevRU.BeginPreview(r, background);
  98. Render();
  99. prevRU.EndAndDrawPreview(r);
  100. }
  101. public void Update()
  102. {
  103. if (!isRunning)
  104. return;
  105. if (ps != null)
  106. {
  107. Repaint();
  108. }
  109. }
  110. public override void Initialize(UnityEngine.Object[] targets)
  111. {
  112. base.Initialize(targets);
  113. }
  114. public void CreatePrevRU()
  115. {
  116. if (prevRU != null)
  117. return;
  118. prevRU = new PreviewRenderUtility(true);
  119. prevRU.cameraFieldOfView = 30.0f;
  120. var cam = prevRU.camera;
  121. cam.cullingMask = 1 << prevCulLay;
  122. cam.allowHDR = false;
  123. cam.allowMSAA = false;
  124. CreateIns();
  125. CreateFloor();
  126. }
  127. void CreateIns()
  128. {
  129. DestoryIns();
  130. ins = GameObject.Instantiate(target) as GameObject;
  131. SetUpInsArr(ins);
  132. prevRU.AddSingleGO(ins);
  133. }
  134. void CreateFloor()
  135. {
  136. fm = Resources.GetBuiltinResource<Mesh>("New-Plane.fbx");
  137. ft = (Texture2D)EditorGUIUtility.Load("Avatar/Textures/AvatarFloor.png");
  138. var s = EditorGUIUtility.LoadRequired("Previews/PreviewPlaneWithShadow.shader") as Shader;
  139. fma = new Material(s);
  140. fma.mainTexture = ft;
  141. fma.mainTextureScale = Vector2.one * 20f;
  142. fma.SetVector("_Alphas", new Vector4(0.5f, 0.3f, 0f, 0f));
  143. fma.hideFlags = HideFlags.HideAndDontSave;
  144. }
  145. bool StartLight()
  146. {
  147. Light[] lights = prevRU.lights;
  148. lights[0].intensity = 1.4f;
  149. lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0f);
  150. lights[1].intensity = 1.4f;
  151. Color ambient = new Color(0.1f, 0.1f, 0.1f, 0f);
  152. InternalEditorUtility.SetCustomLighting(lights, ambient);
  153. bool fog = RenderSettings.fog;
  154. Unsupported.SetRenderSettingsUseFogNoDirty(false);
  155. return fog;
  156. }
  157. void EndLighting(bool old)
  158. {
  159. Unsupported.SetRenderSettingsUseFogNoDirty(old);
  160. InternalEditorUtility.RemoveCustomLighting();
  161. }
  162. public void SetUpInsArr(GameObject go)
  163. {
  164. go.hideFlags = HideFlags.HideAndDontSave;
  165. go.layer = prevCulLay;
  166. foreach (Transform t in go.transform)
  167. SetUpInsArr(t.gameObject);
  168. }
  169. public void DestoryIns()
  170. {
  171. if (ins == null)
  172. return;
  173. GameObject.DestroyImmediate(ins);
  174. ins = null;
  175. }
  176. public override void Cleanup()
  177. {
  178. DestoryIns();
  179. if (prevRU != null)
  180. {
  181. prevRU.Cleanup();
  182. prevRU = null;
  183. }
  184. base.Cleanup();
  185. }
  186. }
  187. public class MyEditor : Editor
  188. {
  189. MyView p;
  190. MyView preview
  191. {
  192. get
  193. {
  194. if (p == null)
  195. {
  196. p = new MyView();
  197. p.Initialize(targets);
  198. p.BindEditor(this);
  199. }
  200. return p;
  201. }
  202. }
  203. public override bool HasPreviewGUI()
  204. {
  205. return preview.HasPreviewGUI();
  206. }
  207. public override void OnPreviewSettings()
  208. {
  209. preview.OnPreviewSettings();
  210. }
  211. public override void OnPreviewGUI(Rect r, GUIStyle background)
  212. {
  213. preview.OnPreviewGUI(r, background);
  214. }
  215. public void Clearup()
  216. {
  217. p.Cleanup();
  218. p = null;
  219. }
  220. }

EditorWindow拓展

  1. public class MyWnd : EditorWindow
  2. {
  3. [MenuItem("编辑器/MyWnd")]
  4. static public void PopUp()
  5. {
  6. var w = EditorWindow.GetWindow<MyWnd>("MyWnd");
  7. w.minSize = new Vector2(800, 600);
  8. w.Show();
  9. }
  10. MyEditor e;
  11. GameObject go;
  12. GameObject pf;
  13. private void OnGUI()
  14. {
  15. EditorGUI.BeginChangeCheck();
  16. pf = (GameObject)EditorGUILayout.ObjectField(pf, typeof(GameObject), false);
  17. if (EditorGUI.EndChangeCheck())
  18. {
  19. if (e != null)
  20. {
  21. e.Cleanup();
  22. e = null;
  23. }
  24. e = (MyEditor)Editor.CreateEditor(pf, typeof(MyEditor));
  25. }
  26. if (e)
  27. {
  28. e.OnPreviewSettings();
  29. e.OnPreviewGUI(GUILayoutUtility.GetRect(400, 400), EditorStyles.whiteLabel);
  30. Repaint();
  31. }
  32. }
  33. }

动画预览

动画预览相对会简单一点,U3D有一个AnimationClipEditor来预览动画,只是封在了库里没有暴露出来。AnimationClipEditor需要一个AnimClip文件和一个Avatar,比较麻烦。若是Avatar的GameObj上挂载Anim组件可以获取到AnimClip,可以优化下直接拖入Avatar预览动画。

关键点

  • 使用AnimationClipEditor预览动画,使用反射调用库函数优化直接拖入Avatar预览动画
  • AnimationClipEditor类名需要从Debug工具中查看,比如VS断点。然后到U3D的官方C#库函数反射文件中查看
  • 跳转链接:U3D官方C#反射文件

代码示例

反射工具类

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System.Reflection;
  6. public class CSRefUtil
  7. {
  8. static public void SetValuePublic(object obj, string name, params object[] param)
  9. {
  10. var filed = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public);
  11. filed.SetValue(obj, param);
  12. }
  13. static public void SetValuePrivate(object obj, string name, params object[] param)
  14. {
  15. var filed = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
  16. filed.SetValue(obj, param);
  17. }
  18. static public T GetValuePublic<T>(object obj, string name, params object[] param)
  19. {
  20. return (T)obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public).GetValue(obj);
  21. }
  22. static public T GetValuePrivate<T>(object obj, string name, params object[] param)
  23. {
  24. return (T)obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
  25. }
  26. static public void SetPropertyPublic(object obj, string name, params object[] param)
  27. {
  28. var property = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
  29. property.SetMethod.Invoke(obj, param);
  30. }
  31. static public void SetPropertyPrivate(object obj, string name, params object[] param)
  32. {
  33. var property = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic);
  34. property.SetMethod.Invoke(obj, param);
  35. }
  36. static public T GetPropertyPublic<T>(object obj, string name)
  37. {
  38. var property = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
  39. return (T)property.GetMethod.Invoke(obj, new object[] { });
  40. }
  41. static public T GetPropertyPrivate<T>(object obj, string name, params object[] param)
  42. {
  43. var property = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic);
  44. return (T)property.GetMethod.Invoke(obj, new object[] { });
  45. }
  46. static public T CallMethodPublic<T>(object obj, string name, params object[] param)
  47. {
  48. var method = obj.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public);
  49. return (T)method.Invoke(obj, param);
  50. }
  51. static public T CallMethodPrivate<T>(object obj, string name, params object[] param)
  52. {
  53. var method = obj.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic);
  54. return (T)method.Invoke(obj, param);
  55. }
  56. }

编辑器窗口拓展

  1. public class MyEditor : EditorWindow
  2. {
  3. Editor previewAnimWnd;
  4. AnimationClip previewAnim;
  5. bool isPreviewAnimDirty = false;
  6. object avatarWnd;
  7. Vector2 AnimViewSize = new Vector2(800, 600);
  8. GameObject animGo;
  9. [MenuItem("编辑器/MyEditor")]
  10. public static void PopUp()
  11. {
  12. var win = GetWindow<MyEditor>();
  13. win.minSize = new Vector2(800, 800);
  14. win.Show();
  15. }
  16. void OnGUI()
  17. {
  18. DrawPreviewAnim();
  19. }
  20. // 清理资源
  21. void OnDisable()
  22. {
  23. animGo = null;
  24. previewAnim = null;
  25. if (previewAnimWnd != null)
  26. previewAnimWnd = null;
  27. if (avatarWnd != null)
  28. avatarWnd = null;
  29. }
  30. void SetPreviewAnim(AnimationClip anim)
  31. {
  32. previewAnim = anim;
  33. isPreviewAnimDirty = true;
  34. }
  35. public void DrawPreviewAnim()
  36. {
  37. EditorGUI.BeginChangeCheck();
  38. animGo = (GameObject)EditorGUILayout.ObjectField(animGo, typeof(GameObject), false);
  39. if (EditorGUI.EndChangeCheck())
  40. {
  41. if (animGo != null)
  42. {
  43. var animator = animGo.GetComponent<Animator>();
  44. var anim = animator.runtimeAnimatorController.animationClips[0];
  45. SetPreviewAnim(anim);
  46. }
  47. }
  48. if (isPreviewAnimDirty)
  49. {
  50. isPreviewAnimDirty = false;
  51. if (previewAnim != null)
  52. {
  53. previewAnimWnd = Editor.CreateEditor(previewAnim);
  54. previewAnimWnd.OnInspectorGUI();
  55. avatarWnd = CSRefUtil.GetValuePrivate<object>(previewAnimWnd, "m_AvatarPreview");
  56. CSRefUtil.CallMethodPrivate<object>(avatarWnd, "SetPreview", animGo);
  57. }
  58. }
  59. EditorGUILayout.BeginVertical(GUILayout.Width(AnimViewSize.x), GUILayout.Height(AnimViewSize.y));
  60. //绘制
  61. if (previewAnimWnd != null)
  62. {
  63. using (new EditorGUILayout.HorizontalScope())
  64. {
  65. GUILayout.FlexibleSpace();
  66. previewAnimWnd.OnPreviewSettings();
  67. }
  68. AnimationMode.StartAnimationMode();
  69. previewAnimWnd.OnInteractivePreviewGUI(GUILayoutUtility.GetRect(AnimViewSize.x, AnimViewSize.y), EditorStyles.whiteLabel);
  70. AnimationMode.StopAnimationMode();
  71. }
  72. EditorGUILayout.EndVertical();
  73. }
  74. }

备注

  • U3D对编辑器的很多功能都没有介绍清楚,碰到问题建议Google搜索或去讨论群去问下。
  • 还有布局缩进等不是很常见的功能,建议用到的时候去Google或者浏览官方文档。
  • U3D有对编辑器UI树形控件支持
  • 编辑器拓展开发量大可以考虑使用Unity编辑器扩展Odin插件,不过是收费的

U3D编辑器开发&粒子特效/动画预览器示例的更多相关文章

  1. 李洪强iOS开发之苹果使用预览截图

    李洪强iOS开发之苹果使用预览截图 01 在预览的图片中选中你要截得区域  02 - command + C   03 - Command + N 04 - Command + S (保存)

  2. iOS开发之使用Storyboard预览UI在不同屏幕上的运行效果

    在公司做项目一直使用Storyboard,虽然有时会遇到团队合作的Storyboard冲突问题,但是对于Storyboard开发效率之高还是比较划算的.在之前的博客中也提到过,团队合作使用Storyb ...

  3. 安卓开发实用技巧:TextView预览

    背景: 使用TextView时,为了方便在开发工具中预览效果,需要在TextView中设置文字(如:android:text="Hello World"),但是等到后面提交时,为了 ...

  4. 微信小程序开发之真机预览

    1:真机预览时上传组件的坑: 当在真机里面使用上传组件,当进入选择相片或者拍照的时候,小程序会进入后台,调用APP onHide()方法,选择完返回小程序是会调用App Onshow()方法,然后调用 ...

  5. [js开源组件开发]-手机端照片预览组件

    手机端照片预览组件 可怜的我用着华为3C手机,用别人现成的组件都好卡,为了适应我这种屌丝,于是自己简化写了一版的照片预览效果,暂时无缩放功能,以后可能有空再加吧,你也可以自己加下,这是个github上 ...

  6. Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用(转)

    原文地址:http://blog.csdn.net/yanzi1225627/article/details/8605061# 很多时候,android摄像头模块不仅预览,拍照这么简单,而是需要在预览 ...

  7. 10款经典的web前端特效的预览及源码

    1.CSS3响应式导航菜单 今天我给大家介绍一下如何使用纯CSS来实现的一个响应式导航菜单,我们使用的是HTML5+CSS3技术,当浏览器窗口变小或者使用手机浏览器访问的时候,原本横条菜单会收缩成一个 ...

  8. 10款jquery图片广告特效的预览及源码下载 改自[帅的相对论]

    原文格式有问题,我来排版了一下,分享给大家. 1.jQuery仿海尔官网全屏焦点图特效代码 Query仿海尔官网全屏焦点图特效代码,带有左右箭头的jQuery焦点图切换特效.当焦点图切换时,下方的三块 ...

  9. ueditor编辑器视频上传不能预览的问题

    ps:来源 https://blog.csdn.net/eadela/article/details/76264168 修改ueditor.all.js文件 ueditor.all.js,17769行 ...

  10. Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)

    源码:http://files.cnblogs.com/android100/StandardCamera2013-10-18.zip 废话不说了,就是加个seekbar,拖动的话能够调节焦距,让画面 ...

随机推荐

  1. 如何在Spring Boot开启事务

    说到事务,那什么是事务呢? 事务(Transaction),一般是指要做的或所做的事情. 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行. ...

  2. linux下搭建oh-my-zsh环境

    目标:因为用习惯了zsh的shell环境,所以习惯在服务器上也搭建zsh环境,但是每次搭建都需要Google每一步骤,感觉很麻烦,所以决定记录一下,免得一次次查 1. 安装zsh zsh是一款shel ...

  3. .net 温故知新:【9】.NET日志记录 ILogger使用和原理

    日志 日志作为我们程序记录的"黑匣子"是不论什么系统都会使用到的,比如我们经常使用的log4net就是第三方日志记录提供程序.NET 支持使用各种内置和第三方日志记录提供程序的日志 ...

  4. java 分布式游戏服务器框架,集群游戏服务器框架,游戏服务器网关框架 ioGame 网络游戏服务器框架

    ioGame 国内首个基于蚂蚁金服 SOFABolt 的 java 网络游戏服务器框架:无锁异步化.事件驱动的架构设计 通过 ioGame 可以很容易的搭建出一个集群无中心节点.有状态多进程的分步式游 ...

  5. chronyd为隔离网络设置时间同步

    参考链接:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic ...

  6. Kubernetes_Deployment全解析(无状态的Pod)

    前言 一.创建Deployment 1.1 创建Deployment apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy ...

  7. 【Java并发009】原理层面:ThreadLocal类全解析

    一.前言 在Java多线程模块中,ThreadLocal是比较重要的知识点,虽然ThreadLocal类位于java.lang包,但是这个类基本上仅用于多线程. 二.ThreadLocal类概要 2. ...

  8. 我引用中没有Spire.Pdf,但是发现无法解析的“Spire.Pdf”的不同版本之间存在冲突

    问题: 导出错误!未能加载文件或程序集"Spire.Pdf, Version=8.6.1.0, Culture=neutral, PublicKeyToken=663f351905198cb ...

  9. 机器学习模型评价指标之ROC 曲线、 ROC 的 AUC 和 投资回报率

    前文回顾: 机器学习模型评价指标之混淆矩阵 机器学习模型评价指标之Accuracy.Precision.Recall.F-Score.P-R Curve.AUC.AP 和 mAP 1. 基本指标 1. ...

  10. 关于 .NET 在不同操作系统中 IO 文件路径拼接方法结升级 .NET 7 后注意到的一个小坑

    .NET 现在支持跨平台这件事情已经是众所周知的特点了,虽然平台整体支持跨平台了,但是我们的代码如果真的想要实现跨平台运行其实还是有些小细节要注意的,今天想要记录分享的就是关于 文件I/O操作时路径的 ...