Собственные компоненты в редакторе схем

Стартовая страница Форумы Разработка и интеграция Собственные компоненты в редакторе схем

Просмотр 15 сообщений - с 1 по 15 (из 77 всего)
  • Автор
    Сообщения
  • #9372
    Romiros
    Участник

    Будет ли возможность создания собственных компонентов схем? В виде подключаемых dll или ещё как-нибудь. Например, очень не хватает компонента линия и прогрессбар.

    #9374
    Mikhail
    Модератор

    Такая возможность есть. Посмотрите PlgSchBasicComp

    Прогресс бар, я надеюсь, будет реализован с нашей стороны, а вот линия не планируется, так что присоединяйтесь к разработке.

    #9413
    Romiros
    Участник

    Насколько я понимаю, нужно дописывать собственные компоненты в исходную библиотеку, а потом просто заменять ей имеющуюся?

    #9418
    Mikhail
    Модератор

    Нужно создать свой плагин по аналогии с примером, который будет реализовывать новые компоненты в дополнение к существующим.

    #9784
    Romiros
    Участник

    Созданный компонент не появляется на схеме, хотя в списке присутствует. Я так понимаю он просто не рендерится. Я никогда не косался web разработки, направьте пожалуйста.
    Я взял за основу компонент button, упёрся в css. Как скомпилировать .less файл? Я понимаю что нужно использовать node.js, но не пойму как это сделать в студии. VS2017 у меня.

    P.S. Примера не хватает пошагового. Энтузиастов у нас на форуме полно, только знаний не хватает. Если есть профессиональные программисты, помогли бы примерами.

    #9792
    Mikhail
    Модератор

    Созданный компонент не появляется на схеме, хотя в списке присутствует.

    Посмотрите в консоли браузера, там может быть что-то полезное.

    Я так понимаю он просто не рендерится.

    Вполне возможно. Отрисовка компонентов происходит на JS. Посмотрите этот файл.

    Как скомпилировать .less файл?

    С помощью менеджера расширений VS установить WebCompiler. По правой кнопке на файле можно будет скомпилировать.

    Примера не хватает пошагового.

    Согласен, но пока руки не доходят. Может быть кто-то разберется и снимет видео.

    #9793
    Mikhail
    Модератор

    Веб-программирование достаточно специфическое по сравнению с обычными приложениями. Потребуется разобраться с JavaScript, CSS (Less), HTML5.

    #10183
    slwIs
    Участник

    Для создания собственного контрола нужно:

    1. Написать класс который наследуется от BaseComponent и, если контрол динамический то ещё и от IDynamicComponent.
    Класс пишется по аналогии с базовыми контролами, просто посмотрите как там написано, в основном вся «магия в .js» о чём далее..

    2. Добавить ваш класс реализующий контроллер в BasicCompFactory и в BasicCompLibSpec (предварительно нужно подключить в ресурсы изображение вашего контрола для отображения в приложениии редактора схем)

    3. В файле basiccomprender.js добавить в конце:
    scada.scheme.rendererMap.set(«Scada.Web.Plugins.SchBasicComp.НАЗВАНИЕ_ВАШЕГО_КЛАССА», new scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer());

    и реализовать функции:
    scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype.updateData = function (component, renderContext)
    {…реализация…}

    scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer = function () {
    scada.scheme.ComponentRenderer.call(this);
    };

    scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype = Object.create(scada.scheme.ComponentRenderer.prototype);
    scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.constructor = scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer;

    scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype.createDom = function (component, renderContext) {…реализация…}

    Если нужно могу привести пример а так же пример контрола с условиями.
    Исходя из названия SchBasicComp видно что это работает при добавлении к оригинальным компонентам, но если у вас своя библиотека то структура там та же.

    #10184
    slwIs
    Участник

    Например мы хотим сделать шестерёнку в формате SVG и что бы при значении канала больше нуля она крутилась и меняла цвет.

    1.Добавим класс:

    using Scada.Scheme.Model;
    using Scada.Scheme.Model.DataTypes;
    using Scada.Scheme.Model.PropertyGrid;
    using System;
    using System.Drawing.Design;
    using System.Xml;
    using CM = System.ComponentModel;
    
    namespace Scada.Web.Plugins.SchBasicComp
    {
        /// <summary>
        /// Scheme component that represents fan
        /// <para>Компонент схемы, представляющий шестерню</para>
        /// </summary>
        [Serializable]
        public class Setting : BaseComponent, IDynamicComponent
        {
            /// <summary>
            /// Размер кнопки по умолчанию
            /// </summary>
            public static readonly Size DefaultSize = new Size(200, 198);
    
            /// <summary>
            /// Конструктор
            /// </summary>
            public Setting()
                : base()
            {
                serBinder = PlgUtils.SerializationBinder;
    
                ColorOn = "#009846";
                ColorOff = "gray";
                Dur = "1s";
                Action = Actions.None;
                InCnlNum = 0;
                CtrlCnlNum = 0;
                Size = DefaultSize;
            }
    
            /// <summary>
            /// Получить или установить продолжительность анимации
            /// </summary>
            #region Attributes
            [DisplayName("Dur"), Category(Categories.Behavior)]
            [Description("Продолжительность анимации")]
            [CM.DefaultValue("1s")]
            #endregion
            public string Dur { get; set; }
    
            /// <summary>
            /// Получить или установить цвет контрола в включенном состоянии
            /// </summary>
            #region Attributes
            [DisplayName("ColorOn"), Category(Categories.Appearance)]
            [Description("Цвет в вкюченном состоянии")]
            [CM.DefaultValue("#009846")]
            #endregion
            public string ColorOn { get; set; }
    
            /// <summary>
            /// Получить или установить цвет контрола в выключенном состоянии
            /// </summary>
            #region Attributes
            [DisplayName("ColorOff"), Category(Categories.Appearance)]
            [Description("Цвет в выкюченном состоянии")]
            [CM.DefaultValue("gray")]
            #endregion
            public string ColorOff { get; set; }
    
            /// <summary>
            /// Получить или установить действие
            /// </summary>
            #region Attributes
            [DisplayName("Action"), Category(Categories.Behavior)]
            [Description("The action executed by clicking the left mouse button on the component.")]
            [CM.DefaultValue(Actions.None)]
            #endregion
            public Actions Action { get; set; }
    
            /// <summary>
            /// Получить или установить номер входного канала
            /// </summary>
            #region Attributes
            [DisplayName("Input channel"), Category(Categories.Data)]
            [Description("The input channel number associated with the component.")]
            [CM.DefaultValue(0)]
            #endregion
            public int InCnlNum { get; set; }
    
            /// <summary>
            /// Получить или установить номер канала управления
            /// </summary>
            #region Attributes
            [DisplayName("Output channel"), Category(Categories.Data)]
            [Description("The output channel number associated with the component.")]
            [CM.DefaultValue(0)]
            #endregion
            public int CtrlCnlNum { get; set; }
    
            /// <summary>
            /// Загрузить конфигурацию компонента из XML-узла
            /// </summary>
            public override void LoadFromXml(XmlNode xmlNode)
            {
                base.LoadFromXml(xmlNode);
    
                Dur = xmlNode.GetChildAsString("Dur");
                ColorOn = xmlNode.GetChildAsString("ColorOn");
                ColorOff = xmlNode.GetChildAsString("ColorOff");
    
                Action = xmlNode.GetChildAsEnum<Actions>("Action");
                InCnlNum = xmlNode.GetChildAsInt("InCnlNum");
                CtrlCnlNum = xmlNode.GetChildAsInt("CtrlCnlNum");
            }
    
            /// <summary>
            /// Сохранить конфигурацию компонента в XML-узле
            /// </summary>
            public override void SaveToXml(XmlElement xmlElem)
            {
                base.SaveToXml(xmlElem);
    
                xmlElem.AppendElem("Dur", Dur);
                xmlElem.AppendElem("ColorOn", ColorOn);
                xmlElem.AppendElem("ColorOff", ColorOff);
    
                xmlElem.AppendElem("Action", Action);
                xmlElem.AppendElem("InCnlNum", InCnlNum);
                xmlElem.AppendElem("CtrlCnlNum", CtrlCnlNum);
            }
    
            /// <summary>
            /// Вернуть строковое представление объекта
            /// </summary>
            public override string ToString()
            {
                return BuildDisplayName(ToolTip);
            }
        }
    }
    #10185
    slwIs
    Участник

    2. Добавим в BasicCompLibSpec в метод CreateCompItems():

    new CompItem(Resources.setting, typeof(Setting))

    Добавим в BasicCompFactory в метод CreateComponent:

    else if (NameEquals("Setting", (typeof(Setting)).FullName, typeName, nameIsShort))
                    return new Setting();

    3. Настроим отрисовку контрола в js, дабавив следущие строки:

    /********** Setting Renderer **********/
    
    scada.scheme.SettingRenderer = function () {
        scada.scheme.ComponentRenderer.call(this);
    };
    
    scada.scheme.SettingRenderer.prototype = Object.create(scada.scheme.ComponentRenderer.prototype);
    scada.scheme.SettingRenderer.constructor = scada.scheme.SettingRenderer;
    
    scada.scheme.SettingRenderer.prototype.createDom = function (component, renderContext) {
        var props = component.props;
    	var fComp = $("<svg id='comp" + component.id + "' data-oldval='null' clip-rule='evenodd' fill-rule='evenodd' image-rendering='optimizeQuality' text-rendering='geometricPrecision' shape-rendering='geometricPrecision' viewBox='0 0 210 210'>"+
    	"<g><path fill='"+props.ColorOff+"' d='M101.661,67.429c-19.261,0-34.937,15.353-34.937,34.232s15.672,34.25,34.937,34.25"+
    			"c19.258,0,34.926-15.371,34.926-34.25C136.587,82.779,120.919,67.429,101.661,67.429z M101.661,129.035"+
    			"c-15.468,0-28.044-12.286-28.044-27.375c0-15.081,12.576-27.353,28.044-27.353c15.461,0,28.037,12.272,28.037,27.353"+
    			"C129.698,116.753,117.121,129.035,101.661,129.035z'>"+
    			"<animate id='animatecomp" + component.id + "' attributeName='fill' attributeType='XML' begin='0s' dur='"+props.Dur+"' values='"+props.ColorOff+"' calcMode='discrete' fill='freeze'/>"+
    			"</path>"+
    	"<path fill='"+props.ColorOff+"' d='M176.398,77.21l-0.97-0.344l-3.783-9.019l0.412-0.927c11.442-25.947,10.658-26.723,8.754-28.606"+
    			"l-15.264-14.888c-0.623-0.616-1.714-1.052-2.663-1.052c-0.855,0-3.461,0-26.004,10.21l-0.902,0.404l-9.301-3.747l-0.376-0.923"+
    			"C115.708,2.072,114.616,2.072,111.979,2.072H90.423c-2.627,0-3.826,0-13.653,26.294l-0.369,0.956l-9.251,3.772l-0.884-0.369"+
    			"C51.009,26.29,42.102,23.03,39.779,23.03c-0.945,0-2.04,0.422-2.67,1.041L21.835,39.002c-1.94,1.911-2.741,2.709,9.301,28.119"+
    			"l0.444,0.945l-3.783,9.004l-0.927,0.358C0,87.814,0,88.824,0,91.533v21.112c0,2.713,0,3.837,26.917,13.485l0.963,0.34l3.783,8.983"+
    			"l-0.404,0.92c-11.445,25.961-10.719,26.662-8.768,28.599l15.239,14.913c0.641,0.616,1.743,1.052,2.684,1.052"+
    			"c0.852,0,3.45,0,26.004-10.203l0.902-0.426l9.309,3.765l0.365,0.934c10.608,26.24,11.699,26.24,14.337,26.24h21.563"+
    			"c2.706,0,3.822,0,13.66-26.315l0.372-0.956l9.266-3.754l0.884,0.365c15.246,6.453,24.147,9.706,26.458,9.706"+
    			"c0.938,0,2.044-0.408,2.681-1.041l15.303-14.96c1.925-1.922,2.724-2.713-9.337-28.094l-0.447-0.956l3.779-8.969l0.902-0.354"+
    			"c26.906-10.432,26.906-11.449,26.906-14.158V90.659C203.314,87.943,203.314,86.823,176.398,77.21z M169.741,122.25l-4.946,11.764"+
    			"c-0.379,0.895-0.358,1.922,0.068,2.82c3.482,7.283,8.085,17.415,9.985,22.404l0.537,1.417l-12.805,12.526l-1.342-0.447"+
    			"c-5.071-1.718-15.815-6.077-23.649-9.405c-0.805-0.34-1.814-0.365-2.67-0.011l-11.993,4.849c-0.898,0.365-1.603,1.092-1.94,1.986"+
    			"c-3.386,9.126-7.247,18.735-9.176,22.865l-0.626,1.342H93.007l-0.637-1.267c-2.38-4.731-6.807-15.203-9.913-22.923"+
    			"c-0.333-0.859-1.031-1.564-1.9-1.925l-12.036-4.874c-0.805-0.329-1.9-0.293-2.724,0.072c-7.727,3.536-18.123,8.049-23.069,9.853"+
    			"l-1.374,0.512l-12.812-12.54l0.497-1.406c1.718-4.874,6.088-15.249,9.52-22.983c0.379-0.87,0.394-1.829,0.025-2.713l-4.942-11.739"+
    			"c-0.376-0.895-1.102-1.585-2.022-1.911c-7.831-2.795-18.478-6.8-23.359-8.994l-1.364-0.626v-17.64l1.328-0.637"+
    			"c4.746-2.244,15.371-6.56,23.402-9.663c0.884-0.34,1.575-0.998,1.94-1.865l4.967-11.764c0.379-0.905,0.358-1.933-0.061-2.827"+
    			"c-4.141-8.661-8.335-18.095-9.981-22.414l-0.544-1.421l12.798-12.515l1.338,0.447c4.95,1.657,15.668,5.977,23.692,9.398"+
    			"c0.848,0.351,1.789,0.358,2.652,0.011l11.996-4.871c0.87-0.365,1.578-1.102,1.911-1.986c2.845-7.637,6.925-18.045,9.173-22.858"+
    			"l0.623-1.342h18.177l0.651,1.285c2.351,4.713,6.778,15.203,9.888,22.948c0.347,0.855,1.052,1.557,1.9,1.9l12.014,4.853"+
    			"c0.83,0.344,1.933,0.315,2.702-0.043c7.78-3.554,18.227-8.077,23.116-9.856l1.381-0.483l12.809,12.49l-0.497,1.406"+
    			"c-1.746,4.924-6.109,15.292-9.516,22.983c-0.387,0.877-0.387,1.854-0.018,2.756l4.942,11.76c0.372,0.891,1.102,1.585,2.022,1.918"+
    			"c9.427,3.343,19.022,7.015,23.345,8.947l1.385,0.623v17.608l-1.317,0.644c-4.86,2.323-15.561,6.642-23.445,9.695"+
    			"C170.819,120.697,170.092,121.402,169.741,122.25z'>"+
    			"<animate id='animatecomp2" + component.id + "' attributeName='fill' attributeType='XML' begin='0s' dur='"+props.Dur+"' values='"+props.ColorOff+"' calcMode='discrete' fill='freeze'/>"+
    			"</path>"+
    			"<animateTransform id='animateTransformcomp" + component.id + "' attributeType='XML' attributeName='transform' begin='0s' dur='"+props.Dur+"' type='rotate' from='0 102 110' to='0 102 110' repeatCount='indefinite'/>"+
    	"</g></svg>");
    	
    	this.prepareComponent(fComp, component);
    
    	this.bindAction(fComp, component, renderContext);
    	
        component.dom = fComp;
    };
    
    scada.scheme.SettingRenderer.prototype.updateData = function (component, renderContext) 
    {
    	var props = component.props;
    	var curCnlDataExt = renderContext.curCnlDataMap.get(props.InCnlNum);
    	var Setting = document.getElementById('comp'+component.id);
    	
    	if (Setting && curCnlDataExt) 
    	{
    		if (curCnlDataExt.Val > 0 && (Setting.dataset.oldval == 0 || Setting.dataset.oldval=='null')) 
    		{
    			var AnimEl = document.getElementById('animateTransformcomp' + component.id);
    			AnimEl.setAttribute("from", "0 102 110");
    			AnimEl.setAttribute("to", "360 102 110");
    			AnimEl.beginElement();
    			var AnimElColor = document.getElementById('animatecomp' + component.id);
    			AnimElColor.setAttribute("values", props.ColorOff+";"+props.ColorOn);
    			AnimElColor.beginElement();
    			var AnimElColor2 = document.getElementById('animatecomp2' + component.id);
    			AnimElColor2.setAttribute("values", props.ColorOff+";"+props.ColorOn);
    			AnimElColor2.beginElement();
    			Setting.dataset.oldval = curCnlDataExt.Val;
            }
    		
    		if (curCnlDataExt.Val == 0 && (Setting.dataset.oldval == 1 || Setting.dataset.oldval=='null')) 
    		{
    			var AnimEl = document.getElementById('animateTransformcomp' + component.id);
    			AnimEl.setAttribute("from", "0 102 110");
    			AnimEl.setAttribute("to", "0 102 110");
    			AnimEl.beginElement();
    			var AnimElColor = document.getElementById('animatecomp' + component.id);
    			AnimElColor.setAttribute("values", props.ColorOn+";"+props.ColorOff);
    			AnimElColor.beginElement();
    			var AnimElColor2 = document.getElementById('animatecomp2' + component.id);
    			AnimElColor2.setAttribute("values", props.ColorOn+";"+props.ColorOff);
    			AnimElColor2.beginElement();
    			Setting.dataset.oldval = curCnlDataExt.Val;
    		}
    	}
    }
    /********** Renderer Map **********/
    
    // Add components to the renderer map
    scada.scheme.rendererMap.set("Scada.Web.Plugins.SchBasicComp.Setting", new scada.scheme.SettingRenderer());
    #10186
    slwIs
    Участник

    Вот собственно и всё. В js можно положить в контрол всё что угодно от красочных SVG до элементов <video>, и т.д. всё ограничено только вашей фантазией и нуждами. SVG анимируется с помощью SMIL так что дополнительных библиотек не нужно.

    Основная работа и оригинальность как я и писал производится в .JS.

    • Этот ответ был изменен 5 лет, 8 месяцев назад от slwIs.
    #10190
    Mikhail
    Модератор

    Хорошее описание. Я мог бы его положить в отдельный раздел справки, если Вы оформите текст как в остальных страницах справки.

    Также если есть собранный плагин, то можно выложить его в ропозиторий http://demo.rapidscada.net/plugins/Store/Store.aspx

    #10192
    slwIs
    Участник

    https://drive.google.com/open?id=1UX_xEGvZuwPRIvaOgtsxdvbDhguEjTW1

    Так? Или имеется ввиду собрать html? Тогда не уверен когда смогу найти время.

    • Этот ответ был изменен 5 лет, 8 месяцев назад от slwIs.
    #10194
    Romiros
    Участник

    Спасибо большое за пример. Буду изучать.

    #10195
    Mikhail
    Модератор

    Так? Или имеется ввиду собрать html? Тогда не уверен когда смогу найти время.

    Имел ввиду в виде html с той разметкой, как это сделано в файлах справки.
    В любом случае, большое спасибо за помощь — и запись на форуме и Google Doc очень полезны. Именно наши пользователи помогают Rapid SCADA развиваться.

Просмотр 15 сообщений - с 1 по 15 (из 77 всего)
  • Вы должны авторизироваться для ответа в этой теме.